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

#include <cmath>

#include "impeller/geometry/wangs_formula.h"

namespace impeller {

VertexWriter::VertexWriter(std::vector<Point>& points,
                           std::vector<uint16_t>& indices,
                           std::optional<Matrix> uv_transform)
    : points_(points), indices_(indices), uv_transform_(uv_transform) {}

void VertexWriter::EndContour() {
  if (points_.size() == 0u || contour_start_ == points_.size() - 1) {
    // Empty or first contour.
    return;
  }

  auto start = contour_start_;
  auto end = points_.size() - 1;
  // All filled paths are drawn as if they are closed, but if
  // there is an explicit close then a lineTo to the origin
  // is inserted. This point isn't strictly necesary to
  // correctly render the shape and can be dropped.
  if (points_[end] == points_[start]) {
    end--;
  }

  if (contour_start_ > 0) {
    // Triangle strip break.
    indices_.emplace_back(indices_.back());
    indices_.emplace_back(start);
    indices_.emplace_back(start);

    // If the contour has an odd number of points, insert an extra point when
    // bridging to the next contour to preserve the correct triangle winding
    // order.
    if (previous_contour_odd_points_) {
      indices_.emplace_back(start);
    }
  } else {
    indices_.emplace_back(start);
  }

  size_t a = start + 1;
  size_t b = end;
  while (a < b) {
    indices_.emplace_back(a);
    indices_.emplace_back(b);
    a++;
    b--;
  }
  if (a == b) {
    indices_.emplace_back(a);
    previous_contour_odd_points_ = false;
  } else {
    previous_contour_odd_points_ = true;
  }
  contour_start_ = points_.size();
}

void VertexWriter::Write(Point point) {
  points_.emplace_back(point);
  if (uv_transform_.has_value()) {
    points_.emplace_back(*uv_transform_ * point);
  }
}

/*
 *  Based on: https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Specific_cases
 */

static inline Scalar LinearSolve(Scalar t, Scalar p0, Scalar p1) {
  return p0 + t * (p1 - p0);
}

static inline Scalar QuadraticSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2) {
  return (1 - t) * (1 - t) * p0 +  //
         2 * (1 - t) * t * p1 +    //
         t * t * p2;
}

static inline Scalar QuadraticSolveDerivative(Scalar t,
                                              Scalar p0,
                                              Scalar p1,
                                              Scalar p2) {
  return 2 * (1 - t) * (p1 - p0) +  //
         2 * t * (p2 - p1);
}

static inline Scalar CubicSolve(Scalar t,
                                Scalar p0,
                                Scalar p1,
                                Scalar p2,
                                Scalar p3) {
  return (1 - t) * (1 - t) * (1 - t) * p0 +  //
         3 * (1 - t) * (1 - t) * t * p1 +    //
         3 * (1 - t) * t * t * p2 +          //
         t * t * t * p3;
}

static inline Scalar CubicSolveDerivative(Scalar t,
                                          Scalar p0,
                                          Scalar p1,
                                          Scalar p2,
                                          Scalar p3) {
  return -3 * p0 * (1 - t) * (1 - t) +  //
         p1 * (3 * (1 - t) * (1 - t) - 6 * (1 - t) * t) +
         p2 * (6 * (1 - t) * t - 3 * t * t) +  //
         3 * p3 * t * t;
}

Point LinearPathComponent::Solve(Scalar time) const {
  return {
      LinearSolve(time, p1.x, p2.x),  // x
      LinearSolve(time, p1.y, p2.y),  // y
  };
}

void LinearPathComponent::AppendPolylinePoints(
    std::vector<Point>& points) const {
  if (points.size() == 0 || points.back() != p2) {
    points.push_back(p2);
  }
}

std::vector<Point> LinearPathComponent::Extrema() const {
  return {p1, p2};
}

std::optional<Vector2> LinearPathComponent::GetStartDirection() const {
  if (p1 == p2) {
    return std::nullopt;
  }
  return (p1 - p2).Normalize();
}

std::optional<Vector2> LinearPathComponent::GetEndDirection() const {
  if (p1 == p2) {
    return std::nullopt;
  }
  return (p2 - p1).Normalize();
}

Point QuadraticPathComponent::Solve(Scalar time) const {
  return {
      QuadraticSolve(time, p1.x, cp.x, p2.x),  // x
      QuadraticSolve(time, p1.y, cp.y, p2.y),  // y
  };
}

Point QuadraticPathComponent::SolveDerivative(Scalar time) const {
  return {
      QuadraticSolveDerivative(time, p1.x, cp.x, p2.x),  // x
      QuadraticSolveDerivative(time, p1.y, cp.y, p2.y),  // y
  };
}

void QuadraticPathComponent::AppendPolylinePoints(
    Scalar scale_factor,
    std::vector<Point>& points) const {
  ToLinearPathComponents(scale_factor, [&points](const Point& point) {
    points.emplace_back(point);
  });
}

void QuadraticPathComponent::ToLinearPathComponents(
    Scalar scale_factor,
    const PointProc& proc) const {
  Scalar line_count =
      std::ceilf(ComputeQuadradicSubdivisions(scale_factor, *this));
  for (size_t i = 1; i < line_count; i += 1) {
    proc(Solve(i / line_count));
  }
  proc(p2);
}

void QuadraticPathComponent::ToLinearPathComponents(
    Scalar scale,
    VertexWriter& writer) const {
  Scalar line_count = std::ceilf(ComputeQuadradicSubdivisions(scale, *this));
  for (size_t i = 1; i < line_count; i += 1) {
    writer.Write(Solve(i / line_count));
  }
  writer.Write(p2);
}

std::vector<Point> QuadraticPathComponent::Extrema() const {
  CubicPathComponent elevated(*this);
  return elevated.Extrema();
}

std::optional<Vector2> QuadraticPathComponent::GetStartDirection() const {
  if (p1 != cp) {
    return (p1 - cp).Normalize();
  }
  if (p1 != p2) {
    return (p1 - p2).Normalize();
  }
  return std::nullopt;
}

std::optional<Vector2> QuadraticPathComponent::GetEndDirection() const {
  if (p2 != cp) {
    return (p2 - cp).Normalize();
  }
  if (p2 != p1) {
    return (p2 - p1).Normalize();
  }
  return std::nullopt;
}

Point CubicPathComponent::Solve(Scalar time) const {
  return {
      CubicSolve(time, p1.x, cp1.x, cp2.x, p2.x),  // x
      CubicSolve(time, p1.y, cp1.y, cp2.y, p2.y),  // y
  };
}

Point CubicPathComponent::SolveDerivative(Scalar time) const {
  return {
      CubicSolveDerivative(time, p1.x, cp1.x, cp2.x, p2.x),  // x
      CubicSolveDerivative(time, p1.y, cp1.y, cp2.y, p2.y),  // y
  };
}

void CubicPathComponent::AppendPolylinePoints(
    Scalar scale,
    std::vector<Point>& points) const {
  ToLinearPathComponents(
      scale, [&points](const Point& point) { points.emplace_back(point); });
}

inline QuadraticPathComponent CubicPathComponent::Lower() const {
  return QuadraticPathComponent(3.0 * (cp1 - p1), 3.0 * (cp2 - cp1),
                                3.0 * (p2 - cp2));
}

CubicPathComponent CubicPathComponent::Subsegment(Scalar t0, Scalar t1) const {
  auto p0 = Solve(t0);
  auto p3 = Solve(t1);
  auto d = Lower();
  auto scale = (t1 - t0) * (1.0 / 3.0);
  auto p1 = p0 + scale * d.Solve(t0);
  auto p2 = p3 - scale * d.Solve(t1);
  return CubicPathComponent(p0, p1, p2, p3);
}

void CubicPathComponent::ToLinearPathComponents(Scalar scale,
                                                const PointProc& proc) const {
  Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, *this));
  for (size_t i = 1; i < line_count; i++) {
    proc(Solve(i / line_count));
  }
  proc(p2);
}

void CubicPathComponent::ToLinearPathComponents(Scalar scale,
                                                VertexWriter& writer) const {
  Scalar line_count = std::ceilf(ComputeCubicSubdivisions(scale, *this));
  for (size_t i = 1; i < line_count; i++) {
    writer.Write(Solve(i / line_count));
  }
  writer.Write(p2);
}

static inline bool NearEqual(Scalar a, Scalar b, Scalar epsilon) {
  return (a > (b - epsilon)) && (a < (b + epsilon));
}

static inline bool NearZero(Scalar a) {
  return NearEqual(a, 0.0, 1e-12);
}

static void CubicPathBoundingPopulateValues(std::vector<Scalar>& values,
                                            Scalar p1,
                                            Scalar p2,
                                            Scalar p3,
                                            Scalar p4) {
  const Scalar a = 3.0 * (-p1 + 3.0 * p2 - 3.0 * p3 + p4);
  const Scalar b = 6.0 * (p1 - 2.0 * p2 + p3);
  const Scalar c = 3.0 * (p2 - p1);

  /*
   *  Boundary conditions.
   */
  if (NearZero(a)) {
    if (NearZero(b)) {
      return;
    }

    Scalar t = -c / b;
    if (t >= 0.0 && t <= 1.0) {
      values.emplace_back(t);
    }
    return;
  }

  Scalar b2Minus4AC = (b * b) - (4.0 * a * c);

  if (b2Minus4AC < 0.0) {
    return;
  }

  Scalar rootB2Minus4AC = ::sqrt(b2Minus4AC);

  /* From Numerical Recipes in C.
   *
   * q = -1/2 (b + sign(b) sqrt[b^2 - 4ac])
   * x1 = q / a
   * x2 = c / q
   */
  Scalar q = (b < 0) ? -(b - rootB2Minus4AC) / 2 : -(b + rootB2Minus4AC) / 2;

  {
    Scalar t = q / a;
    if (t >= 0.0 && t <= 1.0) {
      values.emplace_back(t);
    }
  }

  {
    Scalar t = c / q;
    if (t >= 0.0 && t <= 1.0) {
      values.emplace_back(t);
    }
  }
}

std::vector<Point> CubicPathComponent::Extrema() const {
  /*
   *  As described in: https://pomax.github.io/bezierinfo/#extremities
   */
  std::vector<Scalar> values;

  CubicPathBoundingPopulateValues(values, p1.x, cp1.x, cp2.x, p2.x);
  CubicPathBoundingPopulateValues(values, p1.y, cp1.y, cp2.y, p2.y);

  std::vector<Point> points = {p1, p2};

  for (const auto& value : values) {
    points.emplace_back(Solve(value));
  }

  return points;
}

std::optional<Vector2> CubicPathComponent::GetStartDirection() const {
  if (p1 != cp1) {
    return (p1 - cp1).Normalize();
  }
  if (p1 != cp2) {
    return (p1 - cp2).Normalize();
  }
  if (p1 != p2) {
    return (p1 - p2).Normalize();
  }
  return std::nullopt;
}

std::optional<Vector2> CubicPathComponent::GetEndDirection() const {
  if (p2 != cp2) {
    return (p2 - cp2).Normalize();
  }
  if (p2 != cp1) {
    return (p2 - cp1).Normalize();
  }
  if (p2 != p1) {
    return (p2 - p1).Normalize();
  }
  return std::nullopt;
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
    const LinearPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetStartDirection();
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
    const QuadraticPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetStartDirection();
}

std::optional<Vector2> PathComponentStartDirectionVisitor::operator()(
    const CubicPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetStartDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
    const LinearPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetEndDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
    const QuadraticPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetEndDirection();
}

std::optional<Vector2> PathComponentEndDirectionVisitor::operator()(
    const CubicPathComponent* component) {
  if (!component) {
    return std::nullopt;
  }
  return component->GetEndDirection();
}

}  // namespace impeller
