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

#include <optional>
#include <utility>

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "impeller/aiks/image_filter.h"
#include "impeller/aiks/paint_pass_delegate.h"
#include "impeller/entity/contents/atlas_contents.h"
#include "impeller/entity/contents/clip_contents.h"
#include "impeller/entity/contents/solid_rrect_blur_contents.h"
#include "impeller/entity/contents/text_contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/contents/vertices_contents.h"
#include "impeller/entity/geometry/geometry.h"
#include "impeller/geometry/path_builder.h"

namespace impeller {

Canvas::Canvas() {
  Initialize(std::nullopt);
}

Canvas::Canvas(Rect cull_rect) {
  Initialize(cull_rect);
}

Canvas::Canvas(IRect cull_rect) {
  Initialize(Rect::MakeLTRB(cull_rect.GetLeft(), cull_rect.GetTop(),
                            cull_rect.GetRight(), cull_rect.GetBottom()));
}

Canvas::~Canvas() = default;

void Canvas::Initialize(std::optional<Rect> cull_rect) {
  initial_cull_rect_ = cull_rect;
  base_pass_ = std::make_unique<EntityPass>();
  current_pass_ = base_pass_.get();
  xformation_stack_.emplace_back(CanvasStackEntry{.cull_rect = cull_rect});
  FML_DCHECK(GetSaveCount() == 1u);
  FML_DCHECK(base_pass_->GetSubpassesDepth() == 1u);
}

void Canvas::Reset() {
  base_pass_ = nullptr;
  current_pass_ = nullptr;
  xformation_stack_ = {};
}

void Canvas::Save() {
  Save(false);
}

void Canvas::Save(bool create_subpass,
                  BlendMode blend_mode,
                  const std::shared_ptr<ImageFilter>& backdrop_filter) {
  auto entry = CanvasStackEntry{};
  entry.xformation = xformation_stack_.back().xformation;
  entry.cull_rect = xformation_stack_.back().cull_rect;
  entry.clip_depth = xformation_stack_.back().clip_depth;
  if (create_subpass) {
    entry.rendering_mode = Entity::RenderingMode::kSubpass;
    auto subpass = std::make_unique<EntityPass>();
    subpass->SetEnableOffscreenCheckerboard(
        debug_options.offscreen_texture_checkerboard);
    if (backdrop_filter) {
      EntityPass::BackdropFilterProc backdrop_filter_proc =
          [backdrop_filter = backdrop_filter->Clone()](
              const FilterInput::Ref& input, const Matrix& effect_transform,
              Entity::RenderingMode rendering_mode) {
            auto filter = backdrop_filter->WrapInput(input);
            filter->SetEffectTransform(effect_transform);
            filter->SetRenderingMode(rendering_mode);
            return filter;
          };
      subpass->SetBackdropFilter(backdrop_filter_proc);
    }
    subpass->SetBlendMode(blend_mode);
    current_pass_ = GetCurrentPass().AddSubpass(std::move(subpass));
    current_pass_->SetTransformation(xformation_stack_.back().xformation);
    current_pass_->SetClipDepth(xformation_stack_.back().clip_depth);
  }
  xformation_stack_.emplace_back(entry);
}

bool Canvas::Restore() {
  FML_DCHECK(xformation_stack_.size() > 0);
  if (xformation_stack_.size() == 1) {
    return false;
  }
  if (xformation_stack_.back().rendering_mode ==
      Entity::RenderingMode::kSubpass) {
    current_pass_ = GetCurrentPass().GetSuperpass();
    FML_DCHECK(current_pass_);
  }

  bool contains_clips = xformation_stack_.back().contains_clips;
  xformation_stack_.pop_back();

  if (contains_clips) {
    RestoreClip();
  }

  return true;
}

void Canvas::Concat(const Matrix& xformation) {
  xformation_stack_.back().xformation = GetCurrentTransformation() * xformation;
}

void Canvas::PreConcat(const Matrix& xformation) {
  xformation_stack_.back().xformation = xformation * GetCurrentTransformation();
}

void Canvas::ResetTransform() {
  xformation_stack_.back().xformation = {};
}

void Canvas::Transform(const Matrix& xformation) {
  Concat(xformation);
}

const Matrix& Canvas::GetCurrentTransformation() const {
  return xformation_stack_.back().xformation;
}

const std::optional<Rect> Canvas::GetCurrentLocalCullingBounds() const {
  auto cull_rect = xformation_stack_.back().cull_rect;
  if (cull_rect.has_value()) {
    Matrix inverse = xformation_stack_.back().xformation.Invert();
    cull_rect = cull_rect.value().TransformBounds(inverse);
  }
  return cull_rect;
}

void Canvas::Translate(const Vector3& offset) {
  Concat(Matrix::MakeTranslation(offset));
}

void Canvas::Scale(const Vector2& scale) {
  Concat(Matrix::MakeScale(scale));
}

void Canvas::Scale(const Vector3& scale) {
  Concat(Matrix::MakeScale(scale));
}

void Canvas::Skew(Scalar sx, Scalar sy) {
  Concat(Matrix::MakeSkew(sx, sy));
}

void Canvas::Rotate(Radians radians) {
  Concat(Matrix::MakeRotationZ(radians));
}

size_t Canvas::GetSaveCount() const {
  return xformation_stack_.size();
}

void Canvas::RestoreToCount(size_t count) {
  while (GetSaveCount() > count) {
    if (!Restore()) {
      return;
    }
  }
}

void Canvas::DrawPath(const Path& path, const Paint& paint) {
  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);
  entity.SetContents(paint.WithFilters(paint.CreateContentsForEntity(path)));

  GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawPaint(const Paint& paint) {
  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);
  entity.SetContents(paint.CreateContentsForEntity({}, true));

  GetCurrentPass().AddEntity(entity);
}

bool Canvas::AttemptDrawBlurredRRect(const Rect& rect,
                                     Scalar corner_radius,
                                     const Paint& paint) {
  Paint new_paint = paint;
  if (new_paint.color_source.GetType() != ColorSource::Type::kColor ||
      new_paint.style != Paint::Style::kFill) {
    return false;
  }

  if (!new_paint.mask_blur_descriptor.has_value() ||
      new_paint.mask_blur_descriptor->style !=
          FilterContents::BlurStyle::kNormal) {
    return false;
  }

  // For symmetrically mask blurred solid RRects, absorb the mask blur and use
  // a faster SDF approximation.

  auto contents = std::make_shared<SolidRRectBlurContents>();
  contents->SetColor(new_paint.color);
  contents->SetSigma(new_paint.mask_blur_descriptor->sigma);
  contents->SetRRect(rect, corner_radius);

  new_paint.mask_blur_descriptor = std::nullopt;

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(new_paint.blend_mode);
  entity.SetContents(new_paint.WithFilters(std::move(contents)));

  GetCurrentPass().AddEntity(entity);

  return true;
}

void Canvas::DrawRect(Rect rect, const Paint& paint) {
  if (paint.style == Paint::Style::kStroke) {
    DrawPath(PathBuilder{}.AddRect(rect).TakePath(), paint);
    return;
  }

  if (AttemptDrawBlurredRRect(rect, 0, paint)) {
    return;
  }

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);
  entity.SetContents(paint.WithFilters(
      paint.CreateContentsForGeometry(Geometry::MakeRect(rect))));

  GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawRRect(Rect rect, Scalar corner_radius, const Paint& paint) {
  if (AttemptDrawBlurredRRect(rect, corner_radius, paint)) {
    return;
  }
  auto path = PathBuilder{}
                  .SetConvexity(Convexity::kConvex)
                  .AddRoundedRect(rect, corner_radius)
                  .SetBounds(rect)
                  .TakePath();
  if (paint.style == Paint::Style::kFill) {
    Entity entity;
    entity.SetTransformation(GetCurrentTransformation());
    entity.SetClipDepth(GetClipDepth());
    entity.SetBlendMode(paint.blend_mode);
    entity.SetContents(paint.WithFilters(
        paint.CreateContentsForGeometry(Geometry::MakeFillPath(path))));

    GetCurrentPass().AddEntity(entity);
    return;
  }
  DrawPath(path, paint);
}

void Canvas::DrawCircle(Point center, Scalar radius, const Paint& paint) {
  Size half_size(radius, radius);
  if (AttemptDrawBlurredRRect(
          Rect::MakeOriginSize(center - half_size, half_size * 2), radius,
          paint)) {
    return;
  }
  auto circle_path =
      PathBuilder{}
          .AddCircle(center, radius)
          .SetConvexity(Convexity::kConvex)
          .SetBounds(Rect::MakeLTRB(center.x - radius, center.y - radius,
                                    center.x + radius, center.y + radius))
          .TakePath();
  DrawPath(circle_path, paint);
}

void Canvas::ClipPath(const Path& path, Entity::ClipOperation clip_op) {
  ClipGeometry(Geometry::MakeFillPath(path), clip_op);
  if (clip_op == Entity::ClipOperation::kIntersect) {
    auto bounds = path.GetBoundingBox();
    if (bounds.has_value()) {
      IntersectCulling(bounds.value());
    }
  }
}

void Canvas::ClipRect(const Rect& rect, Entity::ClipOperation clip_op) {
  auto geometry = Geometry::MakeRect(rect);
  auto& cull_rect = xformation_stack_.back().cull_rect;
  if (clip_op == Entity::ClipOperation::kIntersect &&                        //
      cull_rect.has_value() &&                                               //
      geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)  //
  ) {
    return;  // This clip will do nothing, so skip it.
  }

  ClipGeometry(std::move(geometry), clip_op);
  switch (clip_op) {
    case Entity::ClipOperation::kIntersect:
      IntersectCulling(rect);
      break;
    case Entity::ClipOperation::kDifference:
      SubtractCulling(rect);
      break;
  }
}

void Canvas::ClipRRect(const Rect& rect,
                       Scalar corner_radius,
                       Entity::ClipOperation clip_op) {
  auto path = PathBuilder{}
                  .SetConvexity(Convexity::kConvex)
                  .AddRoundedRect(rect, corner_radius)
                  .SetBounds(rect)
                  .TakePath();

  std::optional<Rect> inner_rect = (corner_radius * 2 < rect.size.width &&
                                    corner_radius * 2 < rect.size.height)
                                       ? rect.Expand(-corner_radius)
                                       : std::make_optional<Rect>();
  auto geometry = Geometry::MakeFillPath(path, inner_rect);
  auto& cull_rect = xformation_stack_.back().cull_rect;
  if (clip_op == Entity::ClipOperation::kIntersect &&                        //
      cull_rect.has_value() &&                                               //
      geometry->CoversArea(xformation_stack_.back().xformation, *cull_rect)  //
  ) {
    return;  // This clip will do nothing, so skip it.
  }

  ClipGeometry(std::move(geometry), clip_op);
  switch (clip_op) {
    case Entity::ClipOperation::kIntersect:
      IntersectCulling(rect);
      break;
    case Entity::ClipOperation::kDifference:
      if (corner_radius <= 0) {
        SubtractCulling(rect);
      } else {
        // We subtract the inner "tall" and "wide" rectangle pieces
        // that fit inside the corners which cover the greatest area
        // without involving the curved corners
        // Since this is a subtract operation, we can subtract each
        // rectangle piece individually without fear of interference.
        if (corner_radius * 2 < rect.size.width) {
          SubtractCulling(Rect::MakeLTRB(
              rect.GetLeft() + corner_radius, rect.GetTop(),
              rect.GetRight() - corner_radius, rect.GetBottom()));
        }
        if (corner_radius * 2 < rect.size.height) {
          SubtractCulling(Rect::MakeLTRB(
              rect.GetLeft(), rect.GetTop() + corner_radius,  //
              rect.GetRight(), rect.GetBottom() - corner_radius));
        }
      }
      break;
  }
}

void Canvas::ClipGeometry(std::unique_ptr<Geometry> geometry,
                          Entity::ClipOperation clip_op) {
  auto contents = std::make_shared<ClipContents>();
  contents->SetGeometry(std::move(geometry));
  contents->SetClipOperation(clip_op);

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetContents(std::move(contents));
  entity.SetClipDepth(GetClipDepth());

  GetCurrentPass().AddEntity(entity);

  ++xformation_stack_.back().clip_depth;
  xformation_stack_.back().contains_clips = true;
}

void Canvas::IntersectCulling(Rect clip_rect) {
  clip_rect = clip_rect.TransformBounds(GetCurrentTransformation());
  std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
  if (cull_rect.has_value()) {
    cull_rect = cull_rect
                    .value()                  //
                    .Intersection(clip_rect)  //
                    .value_or(Rect{});
  } else {
    cull_rect = clip_rect;
  }
}

void Canvas::SubtractCulling(Rect clip_rect) {
  std::optional<Rect>& cull_rect = xformation_stack_.back().cull_rect;
  if (cull_rect.has_value()) {
    clip_rect = clip_rect.TransformBounds(GetCurrentTransformation());
    cull_rect = cull_rect
                    .value()            //
                    .Cutout(clip_rect)  //
                    .value_or(Rect{});
  }
  // else (no cull) diff (any clip) is non-rectangular
}

void Canvas::RestoreClip() {
  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  // This path is empty because ClipRestoreContents just generates a quad that
  // takes up the full render target.
  entity.SetContents(std::make_shared<ClipRestoreContents>());
  entity.SetClipDepth(GetClipDepth());

  GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawPoints(std::vector<Point> points,
                        Scalar radius,
                        const Paint& paint,
                        PointStyle point_style) {
  if (radius <= 0) {
    return;
  }

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);
  entity.SetContents(paint.WithFilters(paint.CreateContentsForGeometry(
      Geometry::MakePointField(std::move(points), radius,
                               /*round=*/point_style == PointStyle::kRound))));

  GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawPicture(const Picture& picture) {
  if (!picture.pass) {
    return;
  }

  // Clone the base pass and account for the CTM updates.
  auto pass = picture.pass->Clone();

  pass->IterateAllElements([&](auto& element) -> bool {
    if (auto entity = std::get_if<Entity>(&element)) {
      entity->IncrementStencilDepth(GetClipDepth());
      entity->SetTransformation(GetCurrentTransformation() *
                                entity->GetTransformation());
      return true;
    }

    if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) {
      subpass->get()->SetClipDepth(subpass->get()->GetClipDepth() +
                                   GetClipDepth());
      return true;
    }

    FML_UNREACHABLE();
  });

  GetCurrentPass().AddSubpassInline(std::move(pass));

  RestoreClip();
}

void Canvas::DrawImage(const std::shared_ptr<Image>& image,
                       Point offset,
                       const Paint& paint,
                       SamplerDescriptor sampler) {
  if (!image) {
    return;
  }

  const auto source = Rect::MakeSize(image->GetSize());
  const auto dest =
      Rect::MakeXYWH(offset.x, offset.y, source.size.width, source.size.height);

  DrawImageRect(image, source, dest, paint, std::move(sampler));
}

void Canvas::DrawImageRect(const std::shared_ptr<Image>& image,
                           Rect source,
                           Rect dest,
                           const Paint& paint,
                           SamplerDescriptor sampler) {
  if (!image || source.size.IsEmpty() || dest.size.IsEmpty()) {
    return;
  }

  auto size = image->GetSize();

  if (size.IsEmpty()) {
    return;
  }

  auto contents = TextureContents::MakeRect(dest);
  contents->SetTexture(image->GetTexture());
  contents->SetSourceRect(source);
  contents->SetSamplerDescriptor(std::move(sampler));
  contents->SetOpacity(paint.color.alpha);
  contents->SetDeferApplyingOpacity(paint.HasColorFilter());

  Entity entity;
  entity.SetBlendMode(paint.blend_mode);
  entity.SetClipDepth(GetClipDepth());
  entity.SetContents(paint.WithFilters(contents));
  entity.SetTransformation(GetCurrentTransformation());

  GetCurrentPass().AddEntity(entity);
}

Picture Canvas::EndRecordingAsPicture() {
  Picture picture;
  picture.pass = std::move(base_pass_);

  Reset();
  Initialize(initial_cull_rect_);

  return picture;
}

EntityPass& Canvas::GetCurrentPass() {
  FML_DCHECK(current_pass_ != nullptr);
  return *current_pass_;
}

size_t Canvas::GetClipDepth() const {
  return xformation_stack_.back().clip_depth;
}

void Canvas::SaveLayer(const Paint& paint,
                       std::optional<Rect> bounds,
                       const std::shared_ptr<ImageFilter>& backdrop_filter) {
  TRACE_EVENT0("flutter", "Canvas::saveLayer");
  Save(true, paint.blend_mode, backdrop_filter);

  auto& new_layer_pass = GetCurrentPass();
  new_layer_pass.SetBoundsLimit(bounds);

  // Only apply opacity peephole on default blending.
  if (paint.blend_mode == BlendMode::kSourceOver) {
    new_layer_pass.SetDelegate(
        std::make_shared<OpacityPeepholePassDelegate>(paint));
  } else {
    new_layer_pass.SetDelegate(std::make_shared<PaintPassDelegate>(paint));
  }
}

void Canvas::DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
                           Point position,
                           const Paint& paint) {
  Entity entity;
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);

  auto text_contents = std::make_shared<TextContents>();
  text_contents->SetTextFrame(text_frame);
  text_contents->SetColor(paint.color);

  entity.SetTransformation(GetCurrentTransformation() *
                           Matrix::MakeTranslation(position));

  // TODO(bdero): This mask blur application is a hack. It will always wind up
  //              doing a gaussian blur that affects the color source itself
  //              instead of just the mask. The color filter text support
  //              needs to be reworked in order to interact correctly with
  //              mask filters.
  //              https://github.com/flutter/flutter/issues/133297
  entity.SetContents(
      paint.WithFilters(paint.WithMaskBlur(std::move(text_contents), true)));

  GetCurrentPass().AddEntity(entity);
}

static bool UseColorSourceContents(
    const std::shared_ptr<VerticesGeometry>& vertices,
    const Paint& paint) {
  // If there are no vertex color or texture coordinates. Or if there
  // are vertex coordinates then only if the contents are an image or
  // a solid color.
  if (vertices->HasVertexColors()) {
    return false;
  }
  if (vertices->HasTextureCoordinates() &&
      (paint.color_source.GetType() == ColorSource::Type::kImage ||
       paint.color_source.GetType() == ColorSource::Type::kColor)) {
    return true;
  }
  return !vertices->HasTextureCoordinates();
}

void Canvas::DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
                          BlendMode blend_mode,
                          const Paint& paint) {
  // Override the blend mode with kDestination in order to match the behavior
  // of Skia's SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER flag, which
  // is enabled when the Flutter engine builds Skia.
  if (paint.color_source.GetType() == ColorSource::Type::kColor) {
    blend_mode = BlendMode::kDestination;
  }

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);

  // If there are no vertex color or texture coordinates. Or if there
  // are vertex coordinates then only if the contents are an image.
  if (UseColorSourceContents(vertices, paint)) {
    auto contents = paint.CreateContentsForGeometry(vertices);
    entity.SetContents(paint.WithFilters(std::move(contents)));
    GetCurrentPass().AddEntity(entity);
    return;
  }

  auto src_paint = paint;
  src_paint.color = paint.color.WithAlpha(1.0);

  std::shared_ptr<Contents> src_contents =
      src_paint.CreateContentsForGeometry(vertices);
  if (vertices->HasTextureCoordinates()) {
    // If the color source has an intrinsic size, then we use that to
    // create the src contents as a simplification. Otherwise we use
    // the extent of the texture coordinates to determine how large
    // the src contents should be. If neither has a value we fall back
    // to using the geometry coverage data.
    Rect src_coverage;
    auto size = src_contents->GetColorSourceSize();
    if (size.has_value()) {
      src_coverage = Rect::MakeXYWH(0, 0, size->width, size->height);
    } else {
      auto cvg = vertices->GetCoverage(Matrix{});
      FML_CHECK(cvg.has_value());
      src_coverage =
          // Covered by FML_CHECK.
          // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
          vertices->GetTextureCoordinateCoverge().value_or(cvg.value());
    }
    src_contents =
        src_paint.CreateContentsForGeometry(Geometry::MakeRect(src_coverage));
  }

  auto contents = std::make_shared<VerticesContents>();
  contents->SetAlpha(paint.color.alpha);
  contents->SetBlendMode(blend_mode);
  contents->SetGeometry(vertices);
  contents->SetSourceContents(std::move(src_contents));
  entity.SetContents(paint.WithFilters(std::move(contents)));

  GetCurrentPass().AddEntity(entity);
}

void Canvas::DrawAtlas(const std::shared_ptr<Image>& atlas,
                       std::vector<Matrix> transforms,
                       std::vector<Rect> texture_coordinates,
                       std::vector<Color> colors,
                       BlendMode blend_mode,
                       SamplerDescriptor sampler,
                       std::optional<Rect> cull_rect,
                       const Paint& paint) {
  if (!atlas) {
    return;
  }

  std::shared_ptr<AtlasContents> contents = std::make_shared<AtlasContents>();
  contents->SetColors(std::move(colors));
  contents->SetTransforms(std::move(transforms));
  contents->SetTextureCoordinates(std::move(texture_coordinates));
  contents->SetTexture(atlas->GetTexture());
  contents->SetSamplerDescriptor(std::move(sampler));
  contents->SetBlendMode(blend_mode);
  contents->SetCullRect(cull_rect);
  contents->SetAlpha(paint.color.alpha);

  Entity entity;
  entity.SetTransformation(GetCurrentTransformation());
  entity.SetClipDepth(GetClipDepth());
  entity.SetBlendMode(paint.blend_mode);
  entity.SetContents(paint.WithFilters(contents));

  GetCurrentPass().AddEntity(entity);
}

}  // namespace impeller
