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

#include "flutter/impeller/entity/geometry/circle_geometry.h"

#include "flutter/impeller/entity/geometry/line_geometry.h"

namespace impeller {

CircleGeometry::CircleGeometry(const Point& center, Scalar radius)
    : center_(center), radius_(radius), stroke_width_(-1.0f) {
  FML_DCHECK(radius >= 0);
}

CircleGeometry::CircleGeometry(const Point& center,
                               Scalar radius,
                               Scalar stroke_width)
    : center_(center),
      radius_(radius),
      stroke_width_(std::max(stroke_width, 0.0f)) {
  FML_DCHECK(radius >= 0);
  FML_DCHECK(stroke_width >= 0);
}

GeometryResult CircleGeometry::GetPositionBuffer(const ContentContext& renderer,
                                                 const Entity& entity,
                                                 RenderPass& pass) const {
  auto& transform = entity.GetTransform();

  Scalar half_width = stroke_width_ < 0 ? 0.0
                                        : LineGeometry::ComputePixelHalfWidth(
                                              transform, stroke_width_);

  std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();

  // We call the StrokedCircle method which will simplify to a
  // FilledCircleGenerator if the inner_radius is <= 0.
  auto generator =
      tessellator->StrokedCircle(transform, center_, radius_, half_width);

  return ComputePositionGeometry(generator, entity, pass);
}

// |Geometry|
GeometryResult CircleGeometry::GetPositionUVBuffer(
    Rect texture_coverage,
    Matrix effect_transform,
    const ContentContext& renderer,
    const Entity& entity,
    RenderPass& pass) const {
  auto& transform = entity.GetTransform();
  auto uv_transform =
      texture_coverage.GetNormalizingTransform() * effect_transform;

  Scalar half_width = stroke_width_ < 0 ? 0.0
                                        : LineGeometry::ComputePixelHalfWidth(
                                              transform, stroke_width_);
  std::shared_ptr<Tessellator> tessellator = renderer.GetTessellator();

  // We call the StrokedCircle method which will simplify to a
  // FilledCircleGenerator if the inner_radius is <= 0.
  auto generator =
      tessellator->StrokedCircle(transform, center_, radius_, half_width);

  return ComputePositionUVGeometry(generator, uv_transform, entity, pass);
}

GeometryVertexType CircleGeometry::GetVertexType() const {
  return GeometryVertexType::kPosition;
}

std::optional<Rect> CircleGeometry::GetCoverage(const Matrix& transform) const {
  Point corners[4]{
      {center_.x, center_.y - radius_},
      {center_.x + radius_, center_.y},
      {center_.x, center_.y + radius_},
      {center_.x - radius_, center_.y},
  };

  for (int i = 0; i < 4; i++) {
    corners[i] = transform * corners[i];
  }
  return Rect::MakePointBounds(std::begin(corners), std::end(corners));
}

bool CircleGeometry::CoversArea(const Matrix& transform,
                                const Rect& rect) const {
  return false;
}

bool CircleGeometry::IsAxisAlignedRect() const {
  return false;
}

}  // namespace impeller
