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

#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/time/time_point.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "impeller/base/strings.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/fixtures/cubic_to_quads.comp.h"
#include "impeller/fixtures/golden_heart.h"
#include "impeller/fixtures/quad_polyline.comp.h"
#include "impeller/fixtures/sample.comp.h"
#include "impeller/fixtures/stage1.comp.h"
#include "impeller/fixtures/stage2.comp.h"
#include "impeller/fixtures/stroke.comp.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/path_component.h"
#include "impeller/playground/compute_playground_test.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/compute_command.h"
#include "impeller/renderer/compute_pipeline_builder.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"

namespace impeller {
namespace testing {
using ComputeTest = ComputePlaygroundTest;
INSTANTIATE_COMPUTE_SUITE(ComputeTest);

// TODO(dnfield): Re-enable
// https://github.com/flutter/flutter/issues/122828
TEST_P(ComputeTest, DISABLED_HeartCubicsToStrokeVertices) {
  using CS = CubicToQuadsComputeShader;
  using QS = QuadPolylineComputeShader;
  using SS = StrokeComputeShader;

  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups());

  auto cmd_buffer = context->CreateCommandBuffer();
  auto pass = cmd_buffer->CreateComputePass();
  ASSERT_TRUE(pass && pass->IsValid());

  static constexpr size_t kCubicCount = 6;
  static constexpr Scalar kAccuracy = .1;

  auto quads = CreateHostVisibleDeviceBuffer<CS::Quads<kCubicCount * 10>>(
      context, "Quads");

  // TODO(dnfield): Size this buffer more accurately.
  auto polyline =
      CreateHostVisibleDeviceBuffer<QS::Polyline<kCubicCount * 10 * 10>>(
          context, "polyline");

  auto vertex_buffer_count =
      CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
                                                           "VertexBufferCount");

  // TODO(dnfield): Size this buffer more accurately.
  auto vertex_buffer = CreateHostVisibleDeviceBuffer<
      SS::VertexBuffer<kCubicCount * 10 * 10 * 4>>(context, "VertexBuffer");

  {
    using CubicPipelineBuilder = ComputePipelineBuilder<CS>;
    auto pipeline_desc =
        CubicPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
    ASSERT_TRUE(pipeline_desc.has_value());
    auto compute_pipeline =
        context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
    ASSERT_TRUE(compute_pipeline);

    pass->SetGridSize(ISize(1024, 1));
    pass->SetThreadGroupSize(ISize(1024, 1));

    ComputeCommand cmd;
    cmd.label = "Cubic To Quads";
    cmd.pipeline = compute_pipeline;

    CS::Config config{.accuracy = kAccuracy};
    CS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));
    CS::Cubics<kCubicCount> gpu_cubics;

    gpu_cubics.count = kCubicCount;
    for (size_t i = 0; i < kCubicCount; i++) {
      gpu_cubics.data[i] = {
          golden_heart_cubics[i].p1, golden_heart_cubics[i].cp1,
          golden_heart_cubics[i].cp2, golden_heart_cubics[i].p2};
    }

    CS::BindCubics(
        cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(gpu_cubics));
    CS::BindQuads(cmd, quads->AsBufferView());

    ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
  }

  {
    using QuadPipelineBuilder = ComputePipelineBuilder<QS>;
    auto pipeline_desc =
        QuadPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
    ASSERT_TRUE(pipeline_desc.has_value());
    auto compute_pipeline =
        context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
    ASSERT_TRUE(compute_pipeline);

    pass->SetGridSize(ISize(1024, 1));
    pass->SetThreadGroupSize(ISize(1024, 1));

    ComputeCommand cmd;
    cmd.label = "Quads to Polyline";
    cmd.pipeline = compute_pipeline;

    QS::Config config{.tolerance = kDefaultCurveTolerance};
    QS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));

    QS::BindQuads(cmd, quads->AsBufferView());
    QS::BindPolyline(cmd, polyline->AsBufferView());

    ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
  }

  {
    using StrokePipelineBuilder = ComputePipelineBuilder<SS>;
    auto pipeline_desc =
        StrokePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
    ASSERT_TRUE(pipeline_desc.has_value());
    auto compute_pipeline =
        context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
    ASSERT_TRUE(compute_pipeline);

    pass->SetGridSize(ISize(1024, 1));
    pass->SetThreadGroupSize(ISize(1024, 1));

    ComputeCommand cmd;
    cmd.label = "Compute Stroke";
    cmd.pipeline = compute_pipeline;

    SS::Config config{.width = 1.0f, .cap = 1, .join = 1, .miter_limit = 4.0f};
    SS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));

    SS::BindPolyline(cmd, polyline->AsBufferView());
    SS::BindVertexBufferCount(cmd, vertex_buffer_count->AsBufferView());
    SS::BindVertexBuffer(cmd, vertex_buffer->AsBufferView());

    ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
  }

  ASSERT_TRUE(pass->EncodeCommands());

  fml::AutoResetWaitableEvent latch;
  ASSERT_TRUE(cmd_buffer->SubmitCommands([&latch, quads, polyline,
                                          vertex_buffer_count, vertex_buffer](
                                             CommandBuffer::Status status) {
    EXPECT_EQ(status, CommandBuffer::Status::kCompleted);

    auto* q = reinterpret_cast<CS::Quads<kCubicCount * 10>*>(
        quads->AsBufferView().contents);

    EXPECT_EQ(q->count, golden_heart_quads.size());
    for (size_t i = 0; i < q->count; i++) {
      EXPECT_LT(std::abs(golden_heart_quads[i].p1.x - q->data[i].p1.x), 1e-3);
      EXPECT_LT(std::abs(golden_heart_quads[i].p1.y - q->data[i].p1.y), 1e-3);

      EXPECT_LT(std::abs(golden_heart_quads[i].cp.x - q->data[i].cp.x), 1e-3);
      EXPECT_LT(std::abs(golden_heart_quads[i].cp.y - q->data[i].cp.y), 1e-3);

      EXPECT_LT(std::abs(golden_heart_quads[i].p2.x - q->data[i].p2.x), 1e-3);
      EXPECT_LT(std::abs(golden_heart_quads[i].p2.y - q->data[i].p2.y), 1e-3);
    }

    auto* p = reinterpret_cast<QS::Polyline<kCubicCount * 10 * 10>*>(
        polyline->AsBufferView().contents);
    EXPECT_EQ(p->count, golden_heart_points.size());
    for (size_t i = 0; i < p->count; i++) {
      EXPECT_LT(std::abs(p->data[i].x - golden_heart_points[i].x), 1e-3);
      EXPECT_LT(std::abs(p->data[i].y - golden_heart_points[i].y), 1e-3);
    }

    auto* v = reinterpret_cast<SS::VertexBuffer<kCubicCount * 10 * 10 * 4>*>(
        vertex_buffer->AsBufferView().contents);
    auto* v_count = reinterpret_cast<SS::VertexBufferCount*>(
        vertex_buffer_count->AsBufferView().contents);
    EXPECT_EQ(v_count->count, golden_heart_vertices.size());
    for (size_t i = 0; i < v_count->count; i += 1) {
      EXPECT_LT(std::abs(golden_heart_vertices[i].x - v->position[i].x), 1e-3);
      EXPECT_LT(std::abs(golden_heart_vertices[i].y - v->position[i].y), 1e-3);
    }

    latch.Signal();
  }));

  latch.Wait();

  auto callback = [&](RenderPass& pass) -> bool {
    ContentContext renderer(context);
    if (!renderer.IsValid()) {
      return false;
    }

    using VS = SolidFillPipeline::VertexShader;
    using FS = SolidFillPipeline::FragmentShader;

    Command cmd;
    cmd.label = "Draw Stroke";
    cmd.stencil_reference = 0;  // entity.GetStencilDepth();

    ContentContextOptions options;
    options.sample_count = pass.GetRenderTarget().GetSampleCount();
    options.color_attachment_pixel_format =
        pass.GetRenderTarget().GetRenderTargetPixelFormat();
    options.has_stencil_attachment =
        pass.GetRenderTarget().GetStencilAttachment().has_value();
    options.blend_mode = BlendMode::kSourceIn;  // entity.GetBlendMode();
    options.primitive_type = PrimitiveType::kTriangleStrip;
    options.stencil_compare = CompareFunction::kEqual;
    options.stencil_operation = StencilOperation::kIncrementClamp;

    cmd.pipeline = renderer.GetSolidFillPipeline(options);

    auto count = reinterpret_cast<SS::VertexBufferCount*>(
                     vertex_buffer_count->AsBufferView().contents)
                     ->count;
    auto& host_buffer = pass.GetTransientsBuffer();
    std::vector<uint16_t> indices(count);
    std::iota(std::begin(indices), std::end(indices), 0);

    VertexBuffer render_vertex_buffer{
        .vertex_buffer = vertex_buffer->AsBufferView(),
        .index_buffer = host_buffer.Emplace(
            indices.data(), count * sizeof(uint16_t), alignof(uint16_t)),
        .index_count = count,
        .index_type = IndexType::k16bit};
    cmd.BindVertices(render_vertex_buffer);

    VS::FrameInfo frame_info;
    auto world_matrix = Matrix::MakeScale(GetContentScale());
    frame_info.mvp =
        Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix;
    VS::BindFrameInfo(cmd,
                      pass.GetTransientsBuffer().EmplaceUniform(frame_info));

    FS::FragInfo frag_info;
    frag_info.color = Color::Red().Premultiply();
    FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));

    if (!pass.AddCommand(std::move(cmd))) {
      return false;
    }

    return true;
  };
  ASSERT_TRUE(OpenPlaygroundHere(callback));
}

// TODO(dnfield): Re-enable
// https://github.com/flutter/flutter/issues/122828
TEST_P(ComputeTest, DISABLED_QuadsToPolyline) {
  using QS = QuadPolylineComputeShader;
  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups());

  auto cmd_buffer = context->CreateCommandBuffer();
  auto pass = cmd_buffer->CreateComputePass();
  ASSERT_TRUE(pass && pass->IsValid());

  static constexpr size_t kQuadCount = 26;
  static constexpr size_t kPolylineCount = 1024;

  QS::Quads<kQuadCount> quads;
  quads.count = kQuadCount;
  for (size_t i = 0; i < kQuadCount; i++) {
    quads.data[i] = {golden_heart_quads[i].p1, golden_heart_quads[i].cp,
                     golden_heart_quads[i].p2};
  }

  auto polyline = CreateHostVisibleDeviceBuffer<QS::Polyline<kPolylineCount>>(
      context, "polyline");

  {
    using QuadPipelineBuilder = ComputePipelineBuilder<QS>;
    auto pipeline_desc =
        QuadPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
    ASSERT_TRUE(pipeline_desc.has_value());
    auto compute_pipeline =
        context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
    ASSERT_TRUE(compute_pipeline);

    pass->SetGridSize(ISize(1024, 1));
    pass->SetThreadGroupSize(ISize(1024, 1));

    ComputeCommand cmd;
    cmd.label = "Quads to Polyline";
    cmd.pipeline = compute_pipeline;

    QS::Config config{.tolerance = kDefaultCurveTolerance};
    QS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config));

    QS::BindQuads(cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(quads));
    QS::BindPolyline(cmd, polyline->AsBufferView());

    ASSERT_TRUE(pass->AddCommand(std::move(cmd)));
  }

  ASSERT_TRUE(pass->EncodeCommands());

  fml::AutoResetWaitableEvent latch;
  ASSERT_TRUE(cmd_buffer->SubmitCommands(
      [&latch, polyline](CommandBuffer::Status status) {
        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);

        auto* p = reinterpret_cast<QS::Polyline<kPolylineCount>*>(
            polyline->AsBufferView().contents);

        EXPECT_EQ(p->count, golden_heart_points.size());
        for (size_t i = 0; i < p->count; i++) {
          EXPECT_LT(std::abs(p->data[i].x - golden_heart_points[i].x), 1e-3);
          EXPECT_LT(std::abs(p->data[i].y - golden_heart_points[i].y), 1e-3);
        }
        latch.Signal();
      }));

  latch.Wait();
}

}  // namespace testing
}  // namespace impeller
