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

#ifndef FLUTTER_IMPELLER_GEOMETRY_PATH_BUILDER_H_
#define FLUTTER_IMPELLER_GEOMETRY_PATH_BUILDER_H_

#include "impeller/geometry/path.h"
#include "impeller/geometry/rect.h"
#include "impeller/geometry/scalar.h"

namespace impeller {

class PathBuilder {
 public:
  /// Used for approximating quarter circle arcs with cubic curves. This is the
  /// control point distance which results in the smallest possible unit circle
  /// integration for a right angle arc. It can be used to approximate arcs less
  /// than 90 degrees to great effect by simply reducing it proportionally to
  /// the angle. However, accuracy rapidly diminishes if magnified for obtuse
  /// angle arcs, and so multiple cubic curves should be used when approximating
  /// arcs greater than 90 degrees.
  constexpr static const Scalar kArcApproximationMagic = 0.551915024494f;

  PathBuilder();

  ~PathBuilder();

  Path CopyPath(FillType fill = FillType::kNonZero);

  Path TakePath(FillType fill = FillType::kNonZero);

  /// @brief Reserve [point_size] points and [verb_size] verbs in the underlying
  ///        path buffer.
  void Reserve(size_t point_size, size_t verb_size);

  PathBuilder& SetConvexity(Convexity value);

  PathBuilder& MoveTo(Point point, bool relative = false);

  PathBuilder& Close();

  /// @brief Insert a line from the current position to `point`.
  ///
  /// If `relative` is true, then `point` is relative to the current location.
  PathBuilder& LineTo(Point point, bool relative = false);

  PathBuilder& HorizontalLineTo(Scalar x, bool relative = false);

  PathBuilder& VerticalLineTo(Scalar y, bool relative = false);

  /// @brief Insert a quadradic curve from the current position to `point` using
  /// the control point `controlPoint`.
  ///
  /// If `relative` is true the `point` and `controlPoint` are relative to
  /// current location.
  PathBuilder& QuadraticCurveTo(Point controlPoint,
                                Point point,
                                bool relative = false);

  /// @brief Insert a cubic curve from the curren position to `point` using the
  /// control points `controlPoint1` and `controlPoint2`.
  ///
  /// If `relative` is true the `point`, `controlPoint1`, and `controlPoint2`
  /// are relative to current location.
  PathBuilder& CubicCurveTo(Point controlPoint1,
                            Point controlPoint2,
                            Point point,
                            bool relative = false);

  PathBuilder& AddRect(Rect rect);

  PathBuilder& AddCircle(const Point& center, Scalar radius);

  PathBuilder& AddArc(const Rect& oval_bounds,
                      Radians start,
                      Radians sweep,
                      bool use_center = false);

  PathBuilder& AddOval(const Rect& rect);

  /// @brief Move to point `p1`, then insert a line from `p1` to `p2`.
  PathBuilder& AddLine(const Point& p1, const Point& p2);

  /// @brief Move to point `p1`, then insert a quadradic curve from `p1` to `p2`
  /// with the control point `cp`.
  PathBuilder& AddQuadraticCurve(Point p1, Point cp, Point p2);

  /// @brief Move to point `p1`, then insert a cubic curve from `p1` to `p2`
  /// with control points `cp1` and `cp2`.
  PathBuilder& AddCubicCurve(Point p1, Point cp1, Point cp2, Point p2);

  /// @brief Transform the existing path segments and contours by the given
  /// `offset`.
  PathBuilder& Shift(Point offset);

  /// @brief Set the bounding box that will be used by `Path.GetBoundingBox` in
  /// place of performing the computation.
  ///
  ///        When Impeller recieves Skia Path objects, many of these already
  ///        have computed bounds. This method is used to avoid needlessly
  ///        recomputing these bounds.
  PathBuilder& SetBounds(Rect bounds);

  struct RoundingRadii {
    Point top_left;
    Point bottom_left;
    Point top_right;
    Point bottom_right;

    RoundingRadii() = default;

    RoundingRadii(Scalar p_top_left,
                  Scalar p_bottom_left,
                  Scalar p_top_right,
                  Scalar p_bottom_right)
        : top_left(p_top_left, p_top_left),
          bottom_left(p_bottom_left, p_bottom_left),
          top_right(p_top_right, p_top_right),
          bottom_right(p_bottom_right, p_bottom_right) {}

    explicit RoundingRadii(Scalar radius)
        : top_left(radius, radius),
          bottom_left(radius, radius),
          top_right(radius, radius),
          bottom_right(radius, radius) {}

    explicit RoundingRadii(Point radii)
        : top_left(radii),
          bottom_left(radii),
          top_right(radii),
          bottom_right(radii) {}

    explicit RoundingRadii(Size radii)
        : top_left(radii),
          bottom_left(radii),
          top_right(radii),
          bottom_right(radii) {}

    bool AreAllZero() const {
      return top_left.IsZero() &&     //
             bottom_left.IsZero() &&  //
             top_right.IsZero() &&    //
             bottom_right.IsZero();
    }
  };

  PathBuilder& AddRoundedRect(Rect rect, RoundingRadii radii);

  PathBuilder& AddRoundedRect(Rect rect, Size radii);

  PathBuilder& AddRoundedRect(Rect rect, Scalar radius);

  PathBuilder& AddPath(const Path& path);

 private:
  Point subpath_start_;
  Point current_;
  Path::Data prototype_;

  PathBuilder& AddRoundedRectTopLeft(Rect rect, RoundingRadii radii);

  PathBuilder& AddRoundedRectTopRight(Rect rect, RoundingRadii radii);

  PathBuilder& AddRoundedRectBottomRight(Rect rect, RoundingRadii radii);

  PathBuilder& AddRoundedRectBottomLeft(Rect rect, RoundingRadii radii);

  void AddContourComponent(const Point& destination, bool is_closed = false);

  void SetContourClosed(bool is_closed);

  void AddLinearComponent(const Point& p1, const Point& p2);

  void AddQuadraticComponent(const Point& p1, const Point& cp, const Point& p2);

  void AddCubicComponent(const Point& p1,
                         const Point& cp1,
                         const Point& cp2,
                         const Point& p2);

  /// Compute the bounds of the path unless they are already computed or
  /// set by an external source, such as |SetBounds|. Any call which mutates
  /// the path data can invalidate the computed/set bounds.
  void UpdateBounds();

  std::optional<std::pair<Point, Point>> GetMinMaxCoveragePoints() const;

  PathBuilder(const PathBuilder&) = delete;
  PathBuilder& operator=(const PathBuilder&&) = delete;
};

}  // namespace impeller

#endif  // FLUTTER_IMPELLER_GEOMETRY_PATH_BUILDER_H_
