// 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 <cmath>
#include <memory>
#include <vector>

#include "flutter/fml/mapping.h"
#include "flutter/testing/testing.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/constants.h"
#include "impeller/geometry/matrix.h"
#include "impeller/geometry/quaternion.h"
#include "impeller/geometry/vector.h"
#include "impeller/image/decompressed_image.h"
#include "impeller/playground/playground.h"
#include "impeller/playground/playground_test.h"
#include "impeller/renderer/formats.h"
#include "impeller/scene/animation/animation_clip.h"
#include "impeller/scene/camera.h"
#include "impeller/scene/geometry.h"
#include "impeller/scene/importer/scene_flatbuffers.h"
#include "impeller/scene/material.h"
#include "impeller/scene/mesh.h"
#include "impeller/scene/scene.h"
#include "third_party/flatbuffers/include/flatbuffers/verifier.h"
#include "third_party/imgui/imgui.h"

// #include "third_party/tinygltf/tiny_gltf.h"

namespace impeller {
namespace scene {
namespace testing {

using SceneTest = PlaygroundTest;
INSTANTIATE_PLAYGROUND_SUITE(SceneTest);

TEST_P(SceneTest, CuboidUnlit) {
  auto scene_context = std::make_shared<SceneContext>(GetContext());

  Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
    auto allocator = GetContext()->GetResourceAllocator();
    auto scene = Scene(scene_context);

    {
      Mesh mesh;

      auto material = Material::MakeUnlit();
      material->SetColor(Color::Red());

      Vector3 size(1, 1, 0);
      mesh.AddPrimitive({Geometry::MakeCuboid(size), std::move(material)});

      Node& root = scene.GetRoot();
      root.SetLocalTransform(Matrix::MakeTranslation(-size / 2));
      root.SetMesh(std::move(mesh));
    }

    // Face towards the +Z direction (+X right, +Y up).
    auto camera = Camera::MakePerspective(
                      /* fov */ Radians(kPiOver4),
                      /* position */ {2, 2, -5})
                      .LookAt(
                          /* target */ Vector3(),
                          /* up */ {0, 1, 0});

    scene.Render(render_target, camera);
    return true;
  };

  OpenPlaygroundHere(callback);
}

TEST_P(SceneTest, FlutterLogo) {
  auto allocator = GetContext()->GetResourceAllocator();

  auto mapping =
      flutter::testing::OpenFixtureAsMapping("flutter_logo_baked.glb.ipscene");
  ASSERT_NE(mapping, nullptr);

  flatbuffers::Verifier verifier(mapping->GetMapping(), mapping->GetSize());
  ASSERT_TRUE(fb::VerifySceneBuffer(verifier));

  std::shared_ptr<Node> gltf_scene =
      Node::MakeFromFlatbuffer(*mapping, *allocator);
  ASSERT_NE(gltf_scene, nullptr);
  ASSERT_EQ(gltf_scene->GetChildren().size(), 1u);
  ASSERT_EQ(gltf_scene->GetChildren()[0]->GetMesh().GetPrimitives().size(), 1u);

  auto scene_context = std::make_shared<SceneContext>(GetContext());
  auto scene = Scene(scene_context);
  scene.GetRoot().AddChild(std::move(gltf_scene));
  scene.GetRoot().SetLocalTransform(Matrix::MakeScale({3, 3, 3}));

  Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
    Quaternion rotation({0, 1, 0}, -GetSecondsElapsed() * 0.5);
    Vector3 start_position(-1, -1.5, -5);

    // Face towards the +Z direction (+X right, +Y up).
    auto camera = Camera::MakePerspective(
                      /* fov */ Degrees(60),
                      /* position */ rotation * start_position)
                      .LookAt(
                          /* target */ Vector3(),
                          /* up */ {0, 1, 0});

    scene.Render(render_target, camera);
    return true;
  };

  OpenPlaygroundHere(callback);
}

TEST_P(SceneTest, TwoTriangles) {
  auto allocator = GetContext()->GetResourceAllocator();

  auto mapping =
      flutter::testing::OpenFixtureAsMapping("two_triangles.glb.ipscene");
  ASSERT_NE(mapping, nullptr);

  std::shared_ptr<Node> gltf_scene =
      Node::MakeFromFlatbuffer(*mapping, *allocator);
  ASSERT_NE(gltf_scene, nullptr);

  auto animation = gltf_scene->FindAnimationByName("Metronome");
  ASSERT_NE(animation, nullptr);

  AnimationClip& metronome_clip = gltf_scene->AddAnimation(animation);
  metronome_clip.SetLoop(true);
  metronome_clip.Play();

  auto scene_context = std::make_shared<SceneContext>(GetContext());
  auto scene = Scene(scene_context);
  scene.GetRoot().AddChild(std::move(gltf_scene));

  Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
    ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
    {
      static Scalar playback_time_scale = 1;
      static Scalar weight = 1;
      static bool loop = true;

      ImGui::SliderFloat("Playback time scale", &playback_time_scale, -5, 5);
      ImGui::SliderFloat("Weight", &weight, -2, 2);
      ImGui::Checkbox("Loop", &loop);
      if (ImGui::Button("Play")) {
        metronome_clip.Play();
      }
      if (ImGui::Button("Pause")) {
        metronome_clip.Pause();
      }
      if (ImGui::Button("Stop")) {
        metronome_clip.Stop();
      }

      metronome_clip.SetPlaybackTimeScale(playback_time_scale);
      metronome_clip.SetWeight(weight);
      metronome_clip.SetLoop(loop);
    }

    ImGui::End();
    Node& node = *scene.GetRoot().GetChildren()[0];
    node.SetLocalTransform(node.GetLocalTransform() *
                           Matrix::MakeRotation(0.02, {0, 1, 0, 0}));

    static ImVec2 mouse_pos_prev = ImGui::GetMousePos();
    ImVec2 mouse_pos = ImGui::GetMousePos();
    Vector2 mouse_diff =
        Vector2(mouse_pos.x - mouse_pos_prev.x, mouse_pos.y - mouse_pos_prev.y);

    static Vector3 position(0, 1, -5);
    static Vector3 cam_position = position;
    auto strafe =
        Vector3(ImGui::IsKeyDown(ImGuiKey_D) - ImGui::IsKeyDown(ImGuiKey_A),
                ImGui::IsKeyDown(ImGuiKey_E) - ImGui::IsKeyDown(ImGuiKey_Q),
                ImGui::IsKeyDown(ImGuiKey_W) - ImGui::IsKeyDown(ImGuiKey_S));
    position += strafe * 0.5;
    cam_position = cam_position.Lerp(position, 0.02);

    // Face towards the +Z direction (+X right, +Y up).
    auto camera = Camera::MakePerspective(
                      /* fov */ Degrees(60),
                      /* position */ cam_position)
                      .LookAt(
                          /* target */ cam_position + Vector3(0, 0, 1),
                          /* up */ {0, 1, 0});

    scene.Render(render_target, camera);
    return true;
  };

  OpenPlaygroundHere(callback);
}

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