// 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 "vertices_contents.h"

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/vertices.frag.h"
#include "impeller/entity/vertices.vert.h"
#include "impeller/geometry/color.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/renderer/vertex_buffer.h"

namespace impeller {

VerticesContents::VerticesContents(Vertices vertices)
    : vertices_(std::move(vertices)){};

VerticesContents::~VerticesContents() = default;

std::optional<Rect> VerticesContents::GetCoverage(const Entity& entity) const {
  return vertices_.GetTransformedBoundingBox(entity.GetTransformation());
};

void VerticesContents::SetColor(Color color) {
  color_ = color.Premultiply();
}

void VerticesContents::SetBlendMode(Entity::BlendMode blend_mode) {
  blend_mode_ = blend_mode;
}

static PrimitiveType GetPrimitiveType(const Vertices& vertices) {
  switch (vertices.GetMode()) {
    case VertexMode::kTriangle:
      return PrimitiveType::kTriangle;
    case VertexMode::kTriangleStrip:
      return PrimitiveType::kTriangleStrip;
  }
}

bool VerticesContents::Render(const ContentContext& renderer,
                              const Entity& entity,
                              RenderPass& pass) const {
  if (!vertices_.IsValid()) {
    return true;
  }

  using VS = VerticesPipeline::VertexShader;

  const auto coverage_rect = vertices_.GetBoundingBox();

  if (!coverage_rect.has_value()) {
    return true;
  }

  if (coverage_rect->size.IsEmpty()) {
    return true;
  }

  std::vector<VS::PerVertexData> vertex_data;
  {
    const auto& positions = vertices_.GetPositions();
    const auto& colors = vertices_.GetColors();
    for (size_t i = 0; i < positions.size(); i++) {
      vertex_data.push_back(VS::PerVertexData{
          .position = positions[i],
          // TODO(108047): Blend these colors together when available. Use
          //               colors[i] as the destination and color_ as the
          //               source. Always use color_ when vertex colors are not
          //               supplied.
          .color = i < colors.size() ? colors[i] : color_,
      });
    }
  }

  size_t total_vtx_bytes = vertex_data.size() * sizeof(VS::PerVertexData);
  size_t total_idx_bytes = vertices_.GetIndices().size() * sizeof(uint16_t);

  auto buffer = renderer.GetContext()->GetTransientsAllocator()->CreateBuffer(
      StorageMode::kHostVisible, total_vtx_bytes + total_idx_bytes);

  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(vertex_data.data()),
                              Range{0, total_vtx_bytes}, 0)) {
    return false;
  }
  if (!buffer->CopyHostBuffer(reinterpret_cast<uint8_t*>(const_cast<uint16_t*>(
                                  vertices_.GetIndices().data())),
                              Range{0, total_idx_bytes}, total_vtx_bytes)) {
    return false;
  }

  auto& host_buffer = pass.GetTransientsBuffer();

  VS::FrameInfo frame_info;
  frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
                   entity.GetTransformation();
  Command cmd;
  cmd.label = "Vertices";
  cmd.pipeline =
      renderer.GetVerticesPipeline(OptionsFromPassAndEntity(pass, entity));
  cmd.stencil_reference = entity.GetStencilDepth();
  cmd.primitive_type = GetPrimitiveType(vertices_);
  cmd.BindVertices({
      .vertex_buffer = {.buffer = buffer, .range = Range{0, total_vtx_bytes}},
      .index_buffer = {.buffer = buffer,
                       .range = Range{total_vtx_bytes, total_idx_bytes}},
      .index_count = vertices_.GetIndices().size(),
      .index_type = IndexType::k16bit,
  });
  VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
  pass.AddCommand(std::move(cmd));

  return true;
}

}  // namespace impeller
