// 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 <future>
#include <numeric>

#include "compute_tessellator.h"
#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/core/formats.h"
#include "impeller/core/host_buffer.h"
#include "impeller/display_list/skia_conversions.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/fixtures/golden_paths.h"
#include "impeller/fixtures/sample.comp.h"
#include "impeller/fixtures/stage1.comp.h"
#include "impeller/fixtures/stage2.comp.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/path_component.h"
#include "impeller/playground/compute_playground_test.h"
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/compute_pipeline_builder.h"
#include "impeller/renderer/compute_tessellator.h"
#include "impeller/renderer/path_polyline.comp.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/stroke.comp.h"
#include "third_party/imgui/imgui.h"
#include "third_party/skia/include/utils/SkParsePath.h"

namespace impeller {
namespace testing {

using ComputeSubgroupTest = ComputePlaygroundTest;
INSTANTIATE_COMPUTE_SUITE(ComputeSubgroupTest);

TEST_P(ComputeSubgroupTest, CapabilitiesSuportSubgroups) {
  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
}

TEST_P(ComputeSubgroupTest, PathPlayground) {
  // Renders stroked SVG paths in an interactive playground.
  using SS = StrokeComputeShader;

  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
  char svg_path_data[16384] =
      "M140 20 "
      "C73 20 20 74 20 140 "
      "c0 135 136 170 228 303 "
      "88-132 229-173 229-303 "
      "0-66-54-120-120-120 "
      "-48 0-90 28-109 69 "
      "-19-41-60-69-108-69z";
  size_t vertex_count = 0;
  Scalar stroke_width = 1.0;

  auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
      context, "VertexBuffer");
  auto vertex_buffer_count =
      CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
                                                           "VertexCount");

  auto callback = [&](RenderPass& pass) -> bool {
    ::memset(vertex_buffer_count->OnGetContents(), 0,
             sizeof(SS::VertexBufferCount));
    ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));
    const auto* main_viewport = ImGui::GetMainViewport();
    ImGui::SetNextWindowPos(
        ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20));
    ImGui::Begin("Path data", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
    ImGui::InputTextMultiline("Path", svg_path_data,
                              IM_ARRAYSIZE(svg_path_data));
    ImGui::DragFloat("Stroke width", &stroke_width, .1, 0.0, 25.0);

    SkPath sk_path;
    if (SkParsePath::FromSVGString(svg_path_data, &sk_path)) {
      std::promise<bool> promise;
      auto future = promise.get_future();

      auto path = skia_conversions::ToPath(sk_path);
      auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
      auto status =
          ComputeTessellator{}
              .SetStrokeWidth(stroke_width)
              .Tessellate(path, *host_buffer, context,
                          DeviceBuffer::AsBufferView(vertex_buffer),
                          DeviceBuffer::AsBufferView(vertex_buffer_count),
                          [vertex_buffer_count, &vertex_count,
                           &promise](CommandBuffer::Status status) {
                            vertex_count =
                                reinterpret_cast<SS::VertexBufferCount*>(
                                    vertex_buffer_count->OnGetContents())
                                    ->count;
                            promise.set_value(
                                status == CommandBuffer::Status::kCompleted);
                          });
      switch (status) {
        case ComputeTessellator::Status::kCommandInvalid:
          ImGui::Text("Failed to submit compute job (invalid command)");
          break;
        case ComputeTessellator::Status::kTooManyComponents:
          ImGui::Text("Failed to submit compute job (too many components) ");
          break;
        case ComputeTessellator::Status::kOk:
          break;
      }
      if (!future.get()) {
        ImGui::Text("Failed to submit compute job.");
        return false;
      }
      if (vertex_count > 0) {
        ImGui::Text("Vertex count: %zu", vertex_count);
      }
    } else {
      ImGui::Text("Failed to parse path data");
    }
    ImGui::End();

    ContentContext renderer(context, nullptr);
    if (!renderer.IsValid()) {
      return false;
    }

    using VS = SolidFillPipeline::VertexShader;

    pass.SetCommandLabel("Draw Stroke");
    pass.SetStencilReference(0);

    ContentContextOptions options;
    options.sample_count = pass.GetRenderTarget().GetSampleCount();
    options.color_attachment_pixel_format =
        pass.GetRenderTarget().GetRenderTargetPixelFormat();
    options.has_depth_stencil_attachments =
        pass.GetRenderTarget().GetStencilAttachment().has_value();
    options.blend_mode = BlendMode::kSourceIn;
    options.primitive_type = PrimitiveType::kTriangleStrip;

    options.stencil_mode =
        ContentContextOptions::StencilMode::kLegacyClipIncrement;

    pass.SetPipeline(renderer.GetSolidFillPipeline(options));

    auto count = reinterpret_cast<SS::VertexBufferCount*>(
                     vertex_buffer_count->OnGetContents())
                     ->count;

    pass.SetVertexBuffer(
        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                     .vertex_count = count,
                     .index_type = IndexType::kNone});

    VS::FrameInfo frame_info;
    frame_info.depth = 0.0;
    auto world_matrix = Matrix::MakeScale(GetContentScale());
    frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
    frame_info.color = Color::Red().Premultiply();
    VS::BindFrameInfo(
        pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));

    return pass.Draw().ok();
  };
  ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(ComputeSubgroupTest, LargePath) {
  // The path in here is large enough to highlight issues around exceeding
  // subgroup size.
  using SS = StrokeComputeShader;

  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());
  size_t vertex_count = 0;
  Scalar stroke_width = 1.0;

  auto vertex_buffer = CreateHostVisibleDeviceBuffer<SS::VertexBuffer<2048>>(
      context, "VertexBuffer");
  auto vertex_buffer_count =
      CreateHostVisibleDeviceBuffer<SS::VertexBufferCount>(context,
                                                           "VertexCount");

  auto complex_path =
      PathBuilder{}
          .MoveTo({359.934, 96.6335})
          .CubicCurveTo({358.189, 96.7055}, {356.436, 96.7908},
                        {354.673, 96.8895})
          .CubicCurveTo({354.571, 96.8953}, {354.469, 96.9016},
                        {354.367, 96.9075})
          .CubicCurveTo({352.672, 97.0038}, {350.969, 97.113},
                        {349.259, 97.2355})
          .CubicCurveTo({349.048, 97.2506}, {348.836, 97.2678},
                        {348.625, 97.2834})
          .CubicCurveTo({347.019, 97.4014}, {345.407, 97.5299},
                        {343.789, 97.6722})
          .CubicCurveTo({343.428, 97.704}, {343.065, 97.7402},
                        {342.703, 97.7734})
          .CubicCurveTo({341.221, 97.9086}, {339.736, 98.0505},
                        {338.246, 98.207})
          .CubicCurveTo({337.702, 98.2642}, {337.156, 98.3292},
                        {336.612, 98.3894})
          .CubicCurveTo({335.284, 98.5356}, {333.956, 98.6837},
                        {332.623, 98.8476})
          .CubicCurveTo({332.495, 98.8635}, {332.366, 98.8818},
                        {332.237, 98.8982})
          .LineTo({332.237, 102.601})
          .LineTo({321.778, 102.601})
          .LineTo({321.778, 100.382})
          .CubicCurveTo({321.572, 100.413}, {321.367, 100.442},
                        {321.161, 100.476})
          .CubicCurveTo({319.22, 100.79}, {317.277, 101.123},
                        {315.332, 101.479})
          .CubicCurveTo({315.322, 101.481}, {315.311, 101.482},
                        {315.301, 101.484})
          .LineTo({310.017, 105.94})
          .LineTo({309.779, 105.427})
          .LineTo({314.403, 101.651})
          .CubicCurveTo({314.391, 101.653}, {314.379, 101.656},
                        {314.368, 101.658})
          .CubicCurveTo({312.528, 102.001}, {310.687, 102.366},
                        {308.846, 102.748})
          .CubicCurveTo({307.85, 102.955}, {306.855, 103.182}, {305.859, 103.4})
          .CubicCurveTo({305.048, 103.579}, {304.236, 103.75},
                        {303.425, 103.936})
          .LineTo({299.105, 107.578})
          .LineTo({298.867, 107.065})
          .LineTo({302.394, 104.185})
          .LineTo({302.412, 104.171})
          .CubicCurveTo({301.388, 104.409}, {300.366, 104.67},
                        {299.344, 104.921})
          .CubicCurveTo({298.618, 105.1}, {297.89, 105.269}, {297.165, 105.455})
          .CubicCurveTo({295.262, 105.94}, {293.36, 106.445},
                        {291.462, 106.979})
          .CubicCurveTo({291.132, 107.072}, {290.802, 107.163},
                        {290.471, 107.257})
          .CubicCurveTo({289.463, 107.544}, {288.455, 107.839},
                        {287.449, 108.139})
          .CubicCurveTo({286.476, 108.431}, {285.506, 108.73},
                        {284.536, 109.035})
          .CubicCurveTo({283.674, 109.304}, {282.812, 109.579},
                        {281.952, 109.859})
          .CubicCurveTo({281.177, 110.112}, {280.406, 110.377},
                        {279.633, 110.638})
          .CubicCurveTo({278.458, 111.037}, {277.256, 111.449},
                        {276.803, 111.607})
          .CubicCurveTo({276.76, 111.622}, {276.716, 111.637},
                        {276.672, 111.653})
          .CubicCurveTo({275.017, 112.239}, {273.365, 112.836},
                        {271.721, 113.463})
          .LineTo({271.717, 113.449})
          .CubicCurveTo({271.496, 113.496}, {271.238, 113.559},
                        {270.963, 113.628})
          .CubicCurveTo({270.893, 113.645}, {270.822, 113.663},
                        {270.748, 113.682})
          .CubicCurveTo({270.468, 113.755}, {270.169, 113.834},
                        {269.839, 113.926})
          .CubicCurveTo({269.789, 113.94}, {269.732, 113.957},
                        {269.681, 113.972})
          .CubicCurveTo({269.391, 114.053}, {269.081, 114.143},
                        {268.756, 114.239})
          .CubicCurveTo({268.628, 114.276}, {268.5, 114.314},
                        {268.367, 114.354})
          .CubicCurveTo({268.172, 114.412}, {267.959, 114.478},
                        {267.752, 114.54})
          .CubicCurveTo({263.349, 115.964}, {258.058, 117.695},
                        {253.564, 119.252})
          .CubicCurveTo({253.556, 119.255}, {253.547, 119.258},
                        {253.538, 119.261})
          .CubicCurveTo({251.844, 119.849}, {250.056, 120.474},
                        {248.189, 121.131})
          .CubicCurveTo({248, 121.197}, {247.812, 121.264}, {247.621, 121.331})
          .CubicCurveTo({247.079, 121.522}, {246.531, 121.715},
                        {245.975, 121.912})
          .CubicCurveTo({245.554, 122.06}, {245.126, 122.212},
                        {244.698, 122.364})
          .CubicCurveTo({244.071, 122.586}, {243.437, 122.811},
                        {242.794, 123.04})
          .CubicCurveTo({242.189, 123.255}, {241.58, 123.472},
                        {240.961, 123.693})
          .CubicCurveTo({240.659, 123.801}, {240.357, 123.909},
                        {240.052, 124.018})
          .CubicCurveTo({239.12, 124.351}, {238.18, 124.687}, {237.22, 125.032})
          .LineTo({237.164, 125.003})
          .CubicCurveTo({236.709, 125.184}, {236.262, 125.358},
                        {235.81, 125.538})
          .CubicCurveTo({235.413, 125.68}, {234.994, 125.832},
                        {234.592, 125.977})
          .CubicCurveTo({234.592, 125.977}, {234.591, 125.977},
                        {234.59, 125.977})
          .CubicCurveTo({222.206, 130.435}, {207.708, 135.753},
                        {192.381, 141.429})
          .CubicCurveTo({162.77, 151.336}, {122.17, 156.894}, {84.1123, 160})
          .LineTo({360, 160})
          .LineTo({360, 119.256})
          .LineTo({360, 106.332})
          .LineTo({360, 96.6307})
          .CubicCurveTo({359.978, 96.6317}, {359.956, 96.6326},
                        {359.934, 96.6335})
          .Close()
          .TakePath();

  auto callback = [&](RenderPass& pass) -> bool {
    ::memset(vertex_buffer_count->OnGetContents(), 0,
             sizeof(SS::VertexBufferCount));
    ::memset(vertex_buffer->OnGetContents(), 0, sizeof(SS::VertexBuffer<2048>));

    ContentContext renderer(context, nullptr);
    if (!renderer.IsValid()) {
      return false;
    }

    ComputeTessellator{}
        .SetStrokeWidth(stroke_width)
        .Tessellate(
            complex_path, renderer.GetTransientsBuffer(), context,
            DeviceBuffer::AsBufferView(vertex_buffer),
            DeviceBuffer::AsBufferView(vertex_buffer_count),
            [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) {
              vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
                                 vertex_buffer_count->OnGetContents())
                                 ->count;
            });

    using VS = SolidFillPipeline::VertexShader;

    pass.SetCommandLabel("Draw Stroke");
    pass.SetStencilReference(0);

    ContentContextOptions options;
    options.sample_count = pass.GetRenderTarget().GetSampleCount();
    options.color_attachment_pixel_format =
        pass.GetRenderTarget().GetRenderTargetPixelFormat();
    options.has_depth_stencil_attachments =
        pass.GetRenderTarget().GetStencilAttachment().has_value();
    options.blend_mode = BlendMode::kSourceIn;
    options.primitive_type = PrimitiveType::kTriangleStrip;

    options.stencil_mode =
        ContentContextOptions::StencilMode::kLegacyClipIncrement;

    pass.SetPipeline(renderer.GetSolidFillPipeline(options));

    auto count = reinterpret_cast<SS::VertexBufferCount*>(
                     vertex_buffer_count->OnGetContents())
                     ->count;

    pass.SetVertexBuffer(
        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                     .vertex_count = count,
                     .index_type = IndexType::kNone});

    VS::FrameInfo frame_info;
    frame_info.depth = 0.0;
    auto world_matrix = Matrix::MakeScale(GetContentScale());
    frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
    frame_info.color = Color::Red().Premultiply();
    VS::BindFrameInfo(
        pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));

    return pass.Draw().ok();
  };
  ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) {
  using SS = StrokeComputeShader;

  auto context = GetContext();
  ASSERT_TRUE(context);
  ASSERT_TRUE(context->GetCapabilities()->SupportsComputeSubgroups());

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

  auto path = PathBuilder{}
                  .AddCubicCurve({140, 20}, {73, 20}, {20, 74}, {20, 140})
                  .AddQuadraticCurve({20, 140}, {93, 90}, {100, 42})
                  .TakePath();

  auto tessellator = ComputeTessellator{};

  fml::AutoResetWaitableEvent latch;

  auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
  auto status = tessellator.Tessellate(
      path, *host_buffer, context, DeviceBuffer::AsBufferView(vertex_buffer),
      DeviceBuffer::AsBufferView(vertex_buffer_count),
      [&latch](CommandBuffer::Status status) {
        EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
        latch.Signal();
      });

  ASSERT_EQ(status, ComputeTessellator::Status::kOk);

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

    using VS = SolidFillPipeline::VertexShader;

    pass.SetCommandLabel("Draw Stroke");
    pass.SetStencilReference(0);

    ContentContextOptions options;
    options.sample_count = pass.GetRenderTarget().GetSampleCount();
    options.color_attachment_pixel_format =
        pass.GetRenderTarget().GetRenderTargetPixelFormat();
    options.has_depth_stencil_attachments =
        pass.GetRenderTarget().GetStencilAttachment().has_value();
    options.blend_mode = BlendMode::kSourceIn;
    options.primitive_type = PrimitiveType::kTriangleStrip;

    options.stencil_mode =
        ContentContextOptions::StencilMode::kLegacyClipIncrement;

    pass.SetPipeline(renderer.GetSolidFillPipeline(options));

    auto count = reinterpret_cast<SS::VertexBufferCount*>(
                     vertex_buffer_count->OnGetContents())
                     ->count;

    pass.SetVertexBuffer(
        VertexBuffer{.vertex_buffer = DeviceBuffer::AsBufferView(vertex_buffer),
                     .vertex_count = count,
                     .index_type = IndexType::kNone});

    VS::FrameInfo frame_info;
    frame_info.depth = 0.0;
    auto world_matrix = Matrix::MakeScale(GetContentScale());
    frame_info.mvp = pass.GetOrthographicTransform() * world_matrix;
    frame_info.color = Color::Red().Premultiply();
    VS::BindFrameInfo(
        pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));

    return pass.Draw().ok();
  };
  ASSERT_TRUE(OpenPlaygroundHere(callback));

  // The latch is down here because it's expected that on Metal the backend
  // will take care of synchronizing the buffer between the compute and render
  // pass usages, since it's not MTLHeap allocated. However, if playgrounds
  // are disabled, no render pass actually gets submitted and we need to do a
  // CPU latch here.
  latch.Wait();

  auto vertex_count = reinterpret_cast<SS::VertexBufferCount*>(
                          vertex_buffer_count->OnGetContents())
                          ->count;
  EXPECT_EQ(vertex_count, golden_cubic_and_quad_points.size());
  auto vertex_buffer_data =
      reinterpret_cast<SS::VertexBuffer<2048>*>(vertex_buffer->OnGetContents());
  for (size_t i = 0; i < vertex_count; i++) {
    EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].x -
                       vertex_buffer_data->position[i].x),
              1e-3);
    EXPECT_LT(std::abs(golden_cubic_and_quad_points[i].y -
                       vertex_buffer_data->position[i].y),
              1e-3);
  }
}

}  // namespace testing
}  // namespace impeller
