// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/testing/testing.h"
#include "impeller/geometry/geometry_asserts.h"
#include "impeller/geometry/matrix.h"
#include "impeller/scene/importer/conversions.h"
#include "impeller/scene/importer/importer.h"
#include "impeller/scene/importer/scene_flatbuffers.h"

namespace impeller {
namespace scene {
namespace importer {
namespace testing {

TEST(ImporterTest, CanParseUnskinnedGLTF) {
  auto mapping =
      flutter::testing::OpenFixtureAsMapping("flutter_logo_baked.glb");

  fb::SceneT scene;
  ASSERT_TRUE(ParseGLTF(*mapping, scene));

  ASSERT_EQ(scene.children.size(), 1u);
  auto& node = scene.nodes[scene.children[0]];

  Matrix node_transform = ToMatrix(*node->transform);
  ASSERT_MATRIX_NEAR(node_transform, Matrix());

  ASSERT_EQ(node->mesh_primitives.size(), 1u);
  auto& mesh = *node->mesh_primitives[0];
  ASSERT_EQ(mesh.indices->count, 918u);

  uint16_t first_index =
      *reinterpret_cast<uint16_t*>(mesh.indices->data.data());
  ASSERT_EQ(first_index, 45u);

  ASSERT_EQ(mesh.vertices.type, fb::VertexBuffer::UnskinnedVertexBuffer);
  auto& vertices = mesh.vertices.AsUnskinnedVertexBuffer()->vertices;
  ASSERT_EQ(vertices.size(), 260u);
  auto& vertex = vertices[0];

  Vector3 position = ToVector3(vertex.position());
  ASSERT_VECTOR3_NEAR(position, Vector3(-0.0100185, -0.522907, 0.133178));

  Vector3 normal = ToVector3(vertex.normal());
  ASSERT_VECTOR3_NEAR(normal, Vector3(0.556997, -0.810833, 0.179733));

  Vector4 tangent = ToVector4(vertex.tangent());
  ASSERT_VECTOR4_NEAR(tangent, Vector4(0.155901, -0.110485, -0.981574, 1));

  Vector2 texture_coords = ToVector2(vertex.texture_coords());
  ASSERT_POINT_NEAR(texture_coords, Vector2(0.727937, 0.713817));

  Color color = ToColor(vertex.color());
  ASSERT_COLOR_NEAR(color, Color(0.0221714, 0.467781, 0.921584, 1));
}

TEST(ImporterTest, CanParseSkinnedGLTF) {
  auto mapping = flutter::testing::OpenFixtureAsMapping("two_triangles.glb");

  fb::SceneT scene;
  ASSERT_TRUE(ParseGLTF(*mapping, scene));

  ASSERT_EQ(scene.children.size(), 1u);
  auto& node = scene.nodes[scene.children[0]];

  Matrix node_transform = ToMatrix(*node->transform);
  ASSERT_MATRIX_NEAR(node_transform, Matrix());

  ASSERT_EQ(node->mesh_primitives.size(), 0u);
  ASSERT_EQ(node->children.size(), 2u);

  // The skinned node contains both a skeleton and skinned mesh primitives that
  // reference bones in the skeleton.
  auto& skinned_node = scene.nodes[node->children[0]];
  ASSERT_NE(skinned_node->skin, nullptr);

  ASSERT_EQ(skinned_node->mesh_primitives.size(), 2u);
  auto& bottom_triangle = *skinned_node->mesh_primitives[0];
  ASSERT_EQ(bottom_triangle.indices->count, 3u);

  ASSERT_EQ(bottom_triangle.vertices.type,
            fb::VertexBuffer::SkinnedVertexBuffer);
  auto& vertices = bottom_triangle.vertices.AsSkinnedVertexBuffer()->vertices;
  ASSERT_EQ(vertices.size(), 3u);
  auto& vertex = vertices[0];

  Vector3 position = ToVector3(vertex.vertex().position());
  ASSERT_VECTOR3_NEAR(position, Vector3(1, 1, 0));

  Vector3 normal = ToVector3(vertex.vertex().normal());
  ASSERT_VECTOR3_NEAR(normal, Vector3(0, 0, 1));

  Vector4 tangent = ToVector4(vertex.vertex().tangent());
  ASSERT_VECTOR4_NEAR(tangent, Vector4(1, 0, 0, -1));

  Vector2 texture_coords = ToVector2(vertex.vertex().texture_coords());
  ASSERT_POINT_NEAR(texture_coords, Vector2(0, 1));

  Color color = ToColor(vertex.vertex().color());
  ASSERT_COLOR_NEAR(color, Color(1, 1, 1, 1));

  Vector4 joints = ToVector4(vertex.joints());
  ASSERT_VECTOR4_NEAR(joints, Vector4(0, 0, 0, 0));

  Vector4 weights = ToVector4(vertex.weights());
  ASSERT_VECTOR4_NEAR(weights, Vector4(1, 0, 0, 0));

  ASSERT_EQ(scene.animations.size(), 2u);
  ASSERT_EQ(scene.animations[0]->name, "Idle");
  ASSERT_EQ(scene.animations[1]->name, "Metronome");
  ASSERT_EQ(scene.animations[1]->channels.size(), 6u);
  auto& channel = scene.animations[1]->channels[3];
  ASSERT_EQ(channel->keyframes.type, fb::Keyframes::RotationKeyframes);
  auto* keyframes = channel->keyframes.AsRotationKeyframes();
  ASSERT_EQ(keyframes->values.size(), 40u);
  ASSERT_VECTOR4_NEAR(ToVector4(keyframes->values[0]),
                      Vector4(0.653281, -0.270598, 0.270598, 0.653281));
  ASSERT_VECTOR4_NEAR(ToVector4(keyframes->values[10]),
                      Vector4(0.700151, 0.0989373, -0.0989373, 0.700151));
}

}  // namespace testing
}  // namespace importer
}  // namespace scene
}  // namespace impeller
