// 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.

#define FML_USED_ON_EMBEDDER

#include <memory>

#include "flutter/common/settings.h"
#include "flutter/common/task_runners.h"
#include "flutter/lib/gpu/context.h"
#include "flutter/lib/gpu/shader_library.h"
#include "flutter/lib/gpu/texture.h"
#include "flutter/runtime/dart_isolate.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/testing/dart_fixture.h"
#include "flutter/testing/dart_isolate_runner.h"
#include "flutter/testing/test_dart_native_resolver.h"
#include "flutter/testing/testing.h"
#include "fml/memory/ref_ptr.h"
#include "impeller/fixtures/texture.frag.h"
#include "impeller/fixtures/texture.vert.h"
#include "impeller/playground/playground_test.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/vertex_buffer_builder.h"

#include "gtest/gtest.h"
#include "third_party/imgui/imgui.h"

namespace impeller {
namespace testing {

static void InstantiateTestShaderLibrary(Context::BackendType backend_type) {
  auto fixture =
      flutter::testing::OpenFixtureAsMapping("playground.shaderbundle");
  auto library = flutter::gpu::ShaderLibrary::MakeFromFlatbuffer(
      backend_type, std::move(fixture));
  flutter::gpu::ShaderLibrary::SetOverride(library);
}

class RendererDartTest : public PlaygroundTest,
                         public flutter::testing::DartFixture {
 public:
  RendererDartTest()
      : settings_(CreateSettingsForFixture()),
        vm_ref_(flutter::DartVMRef::Create(settings_)) {
    fml::MessageLoop::EnsureInitializedForCurrentThread();

    current_task_runner_ = fml::MessageLoop::GetCurrent().GetTaskRunner();

    isolate_ = CreateDartIsolate();
    assert(isolate_);
    assert(isolate_->get()->GetPhase() == flutter::DartIsolate::Phase::Running);

    // Set up native callbacks.
    //
    // Note: The Dart isolate is configured (by
    //       `RendererDartTest::CreateDartIsolate`) to use the main thread, so
    //       there's no need for additional synchronization.
    {
      auto set_display_texture = [this](Dart_NativeArguments args) {
        flutter::gpu::Texture* texture =
            tonic::DartConverter<flutter::gpu::Texture*>::FromDart(
                Dart_GetNativeArgument(args, 0));
        assert(texture != nullptr);  // Should always be a valid pointer.
        received_texture_ = texture->GetTexture();
      };
      AddNativeCallback("SetDisplayTexture",
                        CREATE_NATIVE_ENTRY(set_display_texture));
    }
  }

  flutter::testing::AutoIsolateShutdown* GetIsolate() {
    // Sneak the context into the Flutter GPU API.
    assert(GetContext() != nullptr);
    flutter::gpu::Context::SetOverrideContext(GetContext());

    InstantiateTestShaderLibrary(GetContext()->GetBackendType());

    return isolate_.get();
  }

  /// @brief  Run a Dart function that's expected to create a texture and pass
  ///         it back for rendering via `drawToPlayground`.
  std::shared_ptr<Texture> GetRenderedTextureFromDart(
      const char* dart_function_name) {
    bool success =
        GetIsolate()->RunInIsolateScope([this, &dart_function_name]() -> bool {
          Dart_Handle args[] = {tonic::ToDart(GetWindowSize().width),
                                tonic::ToDart(GetWindowSize().height)};
          if (tonic::CheckAndHandleError(
                  ::Dart_Invoke(Dart_RootLibrary(),
                                tonic::ToDart(dart_function_name), 2, args))) {
            return false;
          }
          return true;
        });
    if (!success) {
      FML_LOG(ERROR) << "Failed to invoke dart test function:"
                     << dart_function_name;
      return nullptr;
    }
    if (!received_texture_) {
      FML_LOG(ERROR) << "Dart test function `" << dart_function_name
                     << "` did not invoke `drawToPlaygroundSurface`.";
      return nullptr;
    }
    return received_texture_;
  }

  /// @brief  Invokes a Dart function.
  ///
  ///         Returns false if invoking the function failed or if any unhandled
  ///         exceptions were thrown.
  bool RunDartFunction(const char* dart_function_name) {
    return GetIsolate()->RunInIsolateScope([&dart_function_name]() -> bool {
      if (tonic::CheckAndHandleError(
              ::Dart_Invoke(Dart_RootLibrary(),
                            tonic::ToDart(dart_function_name), 0, nullptr))) {
        return false;
      }
      return true;
    });
  }

  /// @brief  Invokes a Dart function with the window's width and height as
  ///         arguments.
  ///
  ///         Returns false if invoking the function failed or if any unhandled
  ///         exceptions were thrown.
  bool RunDartFunctionWithWindowSize(const char* dart_function_name) {
    return GetIsolate()->RunInIsolateScope(
        [this, &dart_function_name]() -> bool {
          Dart_Handle args[] = {tonic::ToDart(GetWindowSize().width),
                                tonic::ToDart(GetWindowSize().height)};
          if (tonic::CheckAndHandleError(
                  ::Dart_Invoke(Dart_RootLibrary(),
                                tonic::ToDart(dart_function_name), 2, args))) {
            return false;
          }
          return true;
        });
  }

  /// @brief  Call a dart function that produces a texture and render the result
  ///         in the playground.
  ///
  ///         If the playground isn't enabled, the function is simply run once
  ///         in order to verify that it doesn't throw any unhandled exceptions.
  bool RenderDartToPlayground(const char* dart_function_name) {
    if (!IsPlaygroundEnabled()) {
      // If the playground is not enabled, run the function instead to at least
      // verify that it doesn't crash.
      return RunDartFunctionWithWindowSize(dart_function_name);
    }

    auto context = GetContext();
    assert(context != nullptr);

    //------------------------------------------------------------------------------
    /// Prepare pipeline.
    ///

    using TextureVS = TextureVertexShader;
    using TextureFS = TextureFragmentShader;
    using TexturePipelineBuilder = PipelineBuilder<TextureVS, TextureFS>;

    auto pipeline_desc =
        TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
    if (!pipeline_desc.has_value()) {
      FML_LOG(ERROR) << "Failed to create default pipeline descriptor.";
      return false;
    }
    pipeline_desc->SetSampleCount(SampleCount::kCount4);
    pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
    pipeline_desc->SetDepthStencilAttachmentDescriptor(std::nullopt);
    pipeline_desc->SetStencilPixelFormat(PixelFormat::kUnknown);
    pipeline_desc->SetDepthPixelFormat(PixelFormat::kUnknown);

    auto pipeline =
        context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
    if (!pipeline || !pipeline->IsValid()) {
      FML_LOG(ERROR) << "Failed to create default pipeline.";
      return false;
    }

    //------------------------------------------------------------------------------
    /// Prepare vertex data.
    ///

    VertexBufferBuilder<TextureVS::PerVertexData> texture_vtx_builder;

    // Always stretch out the texture to fill the screen.

    // clang-format off
    texture_vtx_builder.AddVertices({
        {{-0.5, -0.5, 0.0}, {0.0, 0.0}},  // 1
        {{ 0.5, -0.5, 0.0}, {1.0, 0.0}},  // 2
        {{ 0.5,  0.5, 0.0}, {1.0, 1.0}},  // 3
        {{-0.5, -0.5, 0.0}, {0.0, 0.0}},  // 1
        {{ 0.5,  0.5, 0.0}, {1.0, 1.0}},  // 3
        {{-0.5,  0.5, 0.0}, {0.0, 1.0}},  // 4
    });
    // clang-format on

    //------------------------------------------------------------------------------
    /// Prepare sampler.
    ///

    const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
    if (!sampler) {
      FML_LOG(ERROR) << "Failed to create default sampler.";
      return false;
    }

    //------------------------------------------------------------------------------
    /// Render to playground.
    ///

    SinglePassCallback callback = [&](RenderPass& pass) {
      auto texture = GetRenderedTextureFromDart(dart_function_name);
      if (!texture) {
        return false;
      }

      auto buffer = HostBuffer::Create(context->GetResourceAllocator());

      pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
          *context->GetResourceAllocator()));

      TextureVS::UniformBuffer uniforms;
      uniforms.mvp = Matrix();
      TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
      TextureFS::BindTextureContents(pass, texture, sampler);

      pass.SetPipeline(pipeline);

      if (!pass.Draw().ok()) {
        return false;
      }
      return true;
    };
    return OpenPlaygroundHere(callback);
  }

 private:
  std::unique_ptr<flutter::testing::AutoIsolateShutdown> CreateDartIsolate() {
    const auto settings = CreateSettingsForFixture();
    flutter::TaskRunners task_runners(flutter::testing::GetCurrentTestName(),
                                      current_task_runner_,  //
                                      current_task_runner_,  //
                                      current_task_runner_,  //
                                      current_task_runner_   //
    );
    return flutter::testing::RunDartCodeInIsolate(
        vm_ref_, settings, task_runners, "main", {},
        flutter::testing::GetDefaultKernelFilePath());
  }

  const flutter::Settings settings_;
  flutter::DartVMRef vm_ref_;
  fml::RefPtr<fml::TaskRunner> current_task_runner_;
  std::unique_ptr<flutter::testing::AutoIsolateShutdown> isolate_;

  std::shared_ptr<Texture> received_texture_;
};

INSTANTIATE_PLAYGROUND_SUITE(RendererDartTest);

TEST_P(RendererDartTest, CanRunDartInPlaygroundFrame) {
  SinglePassCallback callback = [&](RenderPass& pass) {
    ImGui::Begin("Dart test", nullptr);
    ImGui::Text(
        "This test executes Dart code during the playground frame callback.");
    ImGui::End();

    return RunDartFunction("sayHi");
  };
  ASSERT_TRUE(OpenPlaygroundHere(callback));
}

/// These test entries correspond to Dart functions located in
/// `flutter/impeller/fixtures/dart_tests.dart`

TEST_P(RendererDartTest, CanInstantiateFlutterGPUContext) {
  ASSERT_TRUE(RunDartFunction("instantiateDefaultContext"));
}

TEST_P(RendererDartTest, CanCreateShaderLibrary) {
  ASSERT_TRUE(RunDartFunction("canCreateShaderLibrary"));
}

TEST_P(RendererDartTest, CanReflectUniformStructs) {
  ASSERT_TRUE(RunDartFunction("canReflectUniformStructs"));
}

TEST_P(RendererDartTest, UniformBindFailsForInvalidHostBufferOffset) {
  ASSERT_TRUE(RunDartFunction("uniformBindFailsForInvalidHostBufferOffset"));
}

TEST_P(RendererDartTest, CanCreateRenderPassAndSubmit) {
  ASSERT_TRUE(RenderDartToPlayground("canCreateRenderPassAndSubmit"));
}

}  // namespace testing
}  // namespace impeller
