// 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 "impeller/entity/contents/text_contents.h"

#include <optional>
#include <type_traits>
#include <utility>

#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/renderer/formats.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/sampler_descriptor.h"
#include "impeller/renderer/sampler_library.h"
#include "impeller/tessellator/tessellator.h"
#include "impeller/typographer/glyph_atlas.h"
#include "impeller/typographer/lazy_glyph_atlas.h"

namespace impeller {

TextContents::TextContents() = default;

TextContents::~TextContents() = default;

void TextContents::SetTextFrame(const TextFrame& frame) {
  frame_ = frame;
}

void TextContents::SetGlyphAtlas(std::shared_ptr<LazyGlyphAtlas> atlas) {
  lazy_atlas_ = std::move(atlas);
}

std::shared_ptr<GlyphAtlas> TextContents::ResolveAtlas(
    GlyphAtlas::Type type,
    std::shared_ptr<GlyphAtlasContext> atlas_context,
    std::shared_ptr<Context> context) const {
  FML_DCHECK(lazy_atlas_);
  if (lazy_atlas_) {
    return lazy_atlas_->CreateOrGetGlyphAtlas(type, std::move(atlas_context),
                                              std::move(context));
  }

  return nullptr;
}

void TextContents::SetColor(Color color) {
  color_ = color;
}

std::optional<Rect> TextContents::GetCoverage(const Entity& entity) const {
  auto bounds = frame_.GetBounds();
  if (!bounds.has_value()) {
    return std::nullopt;
  }
  return bounds->TransformBounds(entity.GetTransformation());
}

template <class TPipeline>
static bool CommonRender(
    const ContentContext& renderer,
    const Entity& entity,
    RenderPass& pass,
    const Color& color,
    const TextFrame& frame,
    std::shared_ptr<GlyphAtlas>
        atlas,  // NOLINT(performance-unnecessary-value-param)
    Command& cmd) {
  using VS = typename TPipeline::VertexShader;
  using FS = typename TPipeline::FragmentShader;

  // Common vertex uniforms for all glyphs.
  typename VS::FrameInfo frame_info;
  frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
                   entity.GetTransformation();
  VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));

  SamplerDescriptor sampler_desc;
  sampler_desc.min_filter = MinMagFilter::kLinear;
  sampler_desc.mag_filter = MinMagFilter::kLinear;

  typename FS::FragInfo frag_info;
  frag_info.text_color = ToVector(color.Premultiply());
  frag_info.atlas_size =
      Point{static_cast<Scalar>(atlas->GetTexture()->GetSize().width),
            static_cast<Scalar>(atlas->GetTexture()->GetSize().height)};
  FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info));

  // Common fragment uniforms for all glyphs.
  FS::BindGlyphAtlasSampler(
      cmd,                  // command
      atlas->GetTexture(),  // texture
      renderer.GetContext()->GetSamplerLibrary()->GetSampler(
          sampler_desc)  // sampler
  );

  // Common vertex information for all glyphs.
  // All glyphs are given the same vertex information in the form of a
  // unit-sized quad. The size of the glyph is specified in per instance data
  // and the vertex shader uses this to size the glyph correctly. The
  // interpolated vertex information is also used in the fragment shader to
  // sample from the glyph atlas.

  const std::vector<Point> unit_vertex_points = {
      {0, 0}, {1, 0}, {0, 1}, {1, 1}};
  const std::vector<uint32_t> indices = {0, 1, 2, 1, 2, 3};

  VertexBufferBuilder<typename VS::PerVertexData> vertex_builder;

  size_t count = 0;
  for (const auto& run : frame.GetRuns()) {
    count += run.GetGlyphPositions().size();
  }

  vertex_builder.Reserve(count * 4);
  vertex_builder.ReserveIndices(count * 6);

  uint32_t offset = 0u;
  for (auto i = 0u; i < count; i++) {
    for (const auto& index : indices) {
      vertex_builder.AppendIndex(index + offset);
    }
    offset += 4;
  }

  for (const auto& run : frame.GetRuns()) {
    auto font = run.GetFont();
    auto glyph_size_ = ISize::Ceil(font.GetMetrics().GetBoundingBox().size);
    auto glyph_size = Point{static_cast<Scalar>(glyph_size_.width),
                            static_cast<Scalar>(glyph_size_.height)};
    auto metrics_offset =
        Point{font.GetMetrics().min_extent.x, font.GetMetrics().ascent};

    for (const auto& glyph_position : run.GetGlyphPositions()) {
      FontGlyphPair font_glyph_pair{font, glyph_position.glyph};
      auto atlas_glyph_pos = atlas->FindFontGlyphPosition(font_glyph_pair);
      if (!atlas_glyph_pos.has_value()) {
        VALIDATION_LOG << "Could not find glyph position in the atlas.";
        return false;
      }

      auto atlas_position =
          atlas_glyph_pos->origin + Point{1 / atlas_glyph_pos->size.width,
                                          1 / atlas_glyph_pos->size.height};
      auto atlas_glyph_size =
          Point{atlas_glyph_pos->size.width, atlas_glyph_pos->size.height};
      auto offset_glyph_position = glyph_position.position + metrics_offset;

      for (const auto& point : unit_vertex_points) {
        typename VS::PerVertexData vtx;
        vtx.unit_vertex = point;
        vtx.glyph_position = offset_glyph_position;
        vtx.glyph_size = glyph_size;
        vtx.atlas_position = atlas_position;
        vtx.atlas_glyph_size = atlas_glyph_size;
        if constexpr (std::is_same_v<TPipeline, GlyphAtlasPipeline>) {
          vtx.color_glyph =
              glyph_position.glyph.type == Glyph::Type::kBitmap ? 1.0 : 0.0;
        }
        vertex_builder.AppendVertex(std::move(vtx));
      }
    }
  }
  auto vertex_buffer =
      vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer());
  cmd.BindVertices(std::move(vertex_buffer));

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

  return true;
}

bool TextContents::RenderSdf(const ContentContext& renderer,
                             const Entity& entity,
                             RenderPass& pass) const {
  auto atlas =
      ResolveAtlas(GlyphAtlas::Type::kSignedDistanceField,
                   renderer.GetGlyphAtlasContext(), renderer.GetContext());

  if (!atlas || !atlas->IsValid()) {
    VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
    return false;
  }

  // Information shared by all glyph draw calls.
  Command cmd;
  cmd.label = "TextFrameSDF";
  auto opts = OptionsFromPassAndEntity(pass, entity);
  opts.primitive_type = PrimitiveType::kTriangle;
  cmd.pipeline = renderer.GetGlyphAtlasSdfPipeline(opts);
  cmd.stencil_reference = entity.GetStencilDepth();

  return CommonRender<GlyphAtlasSdfPipeline>(renderer, entity, pass, color_,
                                             frame_, atlas, cmd);
}

bool TextContents::Render(const ContentContext& renderer,
                          const Entity& entity,
                          RenderPass& pass) const {
  if (color_.IsTransparent()) {
    return true;
  }

  // This TextContents may be for a frame that doesn't have color, but the
  // lazy atlas for this scene already does have color.
  // Benchmarks currently show that creating two atlases per pass regresses
  // render time. This should get re-evaluated if we start caching atlases
  // between frames or get significantly faster at creating atlases, because
  // we're potentially trading memory for time here.
  auto atlas =
      ResolveAtlas(lazy_atlas_->HasColor() ? GlyphAtlas::Type::kColorBitmap
                                           : GlyphAtlas::Type::kAlphaBitmap,
                   renderer.GetGlyphAtlasContext(), renderer.GetContext());

  if (!atlas || !atlas->IsValid()) {
    VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
    return false;
  }

  // Information shared by all glyph draw calls.
  Command cmd;
  cmd.label = "TextFrame";
  auto opts = OptionsFromPassAndEntity(pass, entity);
  opts.primitive_type = PrimitiveType::kTriangle;
  cmd.pipeline = renderer.GetGlyphAtlasPipeline(opts);
  cmd.stencil_reference = entity.GetStencilDepth();

  return CommonRender<GlyphAtlasPipeline>(renderer, entity, pass, color_,
                                          frame_, atlas, cmd);
}

}  // namespace impeller
