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

#include <optional>
#include <variant>

#include "flutter/fml/logging.h"
#include "impeller/geometry/path_component.h"
#include "impeller/geometry/point.h"

namespace impeller {

Path::Path() : data_(new Data()) {}

Path::Path(Data data) : data_(std::make_shared<Data>(std::move(data))) {}

Path::~Path() = default;

std::tuple<size_t, size_t> Path::Polyline::GetContourPointBounds(
    size_t contour_index) const {
  if (contour_index >= contours.size()) {
    return {points->size(), points->size()};
  }
  const size_t start_index = contours.at(contour_index).start_index;
  const size_t end_index = (contour_index >= contours.size() - 1)
                               ? points->size()
                               : contours.at(contour_index + 1).start_index;
  return std::make_tuple(start_index, end_index);
}

size_t Path::GetComponentCount(std::optional<ComponentType> type) const {
  if (!type.has_value()) {
    return data_->components.size();
  }
  auto type_value = type.value();
  if (type_value == ComponentType::kContour) {
    return data_->contours.size();
  }
  size_t count = 0u;
  for (const auto& component : data_->components) {
    if (component.type == type_value) {
      count++;
    }
  }
  return count;
}

FillType Path::GetFillType() const {
  return data_->fill;
}

bool Path::IsConvex() const {
  return data_->convexity == Convexity::kConvex;
}

bool Path::IsEmpty() const {
  return data_->points.empty();
}

void Path::EnumerateComponents(
    const Applier<LinearPathComponent>& linear_applier,
    const Applier<QuadraticPathComponent>& quad_applier,
    const Applier<CubicPathComponent>& cubic_applier,
    const Applier<ContourComponent>& contour_applier) const {
  auto& points = data_->points;
  size_t currentIndex = 0;
  for (const auto& component : data_->components) {
    switch (component.type) {
      case ComponentType::kLinear:
        if (linear_applier) {
          linear_applier(currentIndex,
                         LinearPathComponent(points[component.index],
                                             points[component.index + 1]));
        }
        break;
      case ComponentType::kQuadratic:
        if (quad_applier) {
          quad_applier(currentIndex,
                       QuadraticPathComponent(points[component.index],
                                              points[component.index + 1],
                                              points[component.index + 2]));
        }
        break;
      case ComponentType::kCubic:
        if (cubic_applier) {
          cubic_applier(currentIndex,
                        CubicPathComponent(points[component.index],
                                           points[component.index + 1],
                                           points[component.index + 2],
                                           points[component.index + 3]));
        }
        break;
      case ComponentType::kContour:
        if (contour_applier) {
          contour_applier(currentIndex, data_->contours[component.index]);
        }
        break;
    }
    currentIndex++;
  }
}

void Path::WritePolyline(Scalar scale, VertexWriter& writer) const {
  auto& path_components = data_->components;
  auto& path_points = data_->points;
  bool started_contour = false;
  bool first_point = true;

  for (size_t component_i = 0; component_i < path_components.size();
       component_i++) {
    const auto& path_component = path_components[component_i];
    switch (path_component.type) {
      case ComponentType::kLinear: {
        const LinearPathComponent* linear =
            reinterpret_cast<const LinearPathComponent*>(
                &path_points[path_component.index]);
        if (first_point) {
          writer.Write(linear->p1);
          first_point = false;
        }
        writer.Write(linear->p2);
        break;
      }
      case ComponentType::kQuadratic: {
        const QuadraticPathComponent* quad =
            reinterpret_cast<const QuadraticPathComponent*>(
                &path_points[path_component.index]);
        if (first_point) {
          writer.Write(quad->p1);
          first_point = false;
        }
        quad->ToLinearPathComponents(scale, writer);
        break;
      }
      case ComponentType::kCubic: {
        const CubicPathComponent* cubic =
            reinterpret_cast<const CubicPathComponent*>(
                &path_points[path_component.index]);
        if (first_point) {
          writer.Write(cubic->p1);
          first_point = false;
        }
        cubic->ToLinearPathComponents(scale, writer);
        break;
      }
      case ComponentType::kContour:
        if (component_i == path_components.size() - 1) {
          // If the last component is a contour, that means it's an empty
          // contour, so skip it.
          continue;
        }
        // The contour component type is the first segment in a contour.
        // Since this should contain the destination (if closed), we
        // can start with this point. If there was already an open
        // contour, or we've reached the end of the verb list, we
        // also close the contour.
        if (started_contour) {
          writer.EndContour();
        }
        started_contour = true;
        first_point = true;
    }
  }
  if (started_contour) {
    writer.EndContour();
  }
}

bool Path::GetLinearComponentAtIndex(size_t index,
                                     LinearPathComponent& linear) const {
  auto& components = data_->components;

  if (index >= components.size()) {
    return false;
  }

  if (components[index].type != ComponentType::kLinear) {
    return false;
  }

  auto& points = data_->points;
  auto point_index = components[index].index;
  linear = LinearPathComponent(points[point_index], points[point_index + 1]);
  return true;
}

bool Path::GetQuadraticComponentAtIndex(
    size_t index,
    QuadraticPathComponent& quadratic) const {
  auto& components = data_->components;

  if (index >= components.size()) {
    return false;
  }

  if (components[index].type != ComponentType::kQuadratic) {
    return false;
  }

  auto& points = data_->points;
  auto point_index = components[index].index;
  quadratic = QuadraticPathComponent(
      points[point_index], points[point_index + 1], points[point_index + 2]);
  return true;
}

bool Path::GetCubicComponentAtIndex(size_t index,
                                    CubicPathComponent& cubic) const {
  auto& components = data_->components;

  if (index >= components.size()) {
    return false;
  }

  if (components[index].type != ComponentType::kCubic) {
    return false;
  }

  auto& points = data_->points;
  auto point_index = components[index].index;
  cubic = CubicPathComponent(points[point_index], points[point_index + 1],
                             points[point_index + 2], points[point_index + 3]);
  return true;
}

bool Path::GetContourComponentAtIndex(size_t index,
                                      ContourComponent& move) const {
  auto& components = data_->components;

  if (index >= components.size()) {
    return false;
  }

  if (components[index].type != ComponentType::kContour) {
    return false;
  }

  move = data_->contours[components[index].index];
  return true;
}

Path::Polyline::Polyline(Path::Polyline::PointBufferPtr point_buffer,
                         Path::Polyline::ReclaimPointBufferCallback reclaim)
    : points(std::move(point_buffer)), reclaim_points_(std::move(reclaim)) {
  FML_DCHECK(points);
}

Path::Polyline::Polyline(Path::Polyline&& other) {
  points = std::move(other.points);
  reclaim_points_ = std::move(other.reclaim_points_);
  contours = std::move(other.contours);
}

Path::Polyline::~Polyline() {
  if (reclaim_points_) {
    points->clear();
    reclaim_points_(std::move(points));
  }
}

Path::Polyline Path::CreatePolyline(
    Scalar scale,
    Path::Polyline::PointBufferPtr point_buffer,
    Path::Polyline::ReclaimPointBufferCallback reclaim) const {
  Polyline polyline(std::move(point_buffer), std::move(reclaim));

  auto& path_components = data_->components;
  auto& path_points = data_->points;

  auto get_path_component = [&path_components, &path_points](
                                size_t component_i) -> PathComponentVariant {
    if (component_i >= path_components.size()) {
      return std::monostate{};
    }
    const auto& component = path_components[component_i];
    switch (component.type) {
      case ComponentType::kLinear:
        return reinterpret_cast<const LinearPathComponent*>(
            &path_points[component.index]);
      case ComponentType::kQuadratic:
        return reinterpret_cast<const QuadraticPathComponent*>(
            &path_points[component.index]);
      case ComponentType::kCubic:
        return reinterpret_cast<const CubicPathComponent*>(
            &path_points[component.index]);
      case ComponentType::kContour:
        return std::monostate{};
    }
  };

  auto compute_contour_start_direction =
      [&get_path_component](size_t current_path_component_index) {
        size_t next_component_index = current_path_component_index + 1;
        while (!std::holds_alternative<std::monostate>(
            get_path_component(next_component_index))) {
          auto next_component = get_path_component(next_component_index);
          auto maybe_vector =
              std::visit(PathComponentStartDirectionVisitor(), next_component);
          if (maybe_vector.has_value()) {
            return maybe_vector.value();
          } else {
            next_component_index++;
          }
        }
        return Vector2(0, -1);
      };

  std::vector<PolylineContour::Component> poly_components;
  std::optional<size_t> previous_path_component_index;
  auto end_contour = [&polyline, &previous_path_component_index,
                      &get_path_component, &poly_components]() {
    // Whenever a contour has ended, extract the exact end direction from
    // the last component.
    if (polyline.contours.empty()) {
      return;
    }

    if (!previous_path_component_index.has_value()) {
      return;
    }

    auto& contour = polyline.contours.back();
    contour.end_direction = Vector2(0, 1);
    contour.components = poly_components;
    poly_components.clear();

    size_t previous_index = previous_path_component_index.value();
    while (!std::holds_alternative<std::monostate>(
        get_path_component(previous_index))) {
      auto previous_component = get_path_component(previous_index);
      auto maybe_vector =
          std::visit(PathComponentEndDirectionVisitor(), previous_component);
      if (maybe_vector.has_value()) {
        contour.end_direction = maybe_vector.value();
        break;
      } else {
        if (previous_index == 0) {
          break;
        }
        previous_index--;
      }
    }
  };

  for (size_t component_i = 0; component_i < path_components.size();
       component_i++) {
    const auto& path_component = path_components[component_i];
    switch (path_component.type) {
      case ComponentType::kLinear:
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = false,
        });
        reinterpret_cast<const LinearPathComponent*>(
            &path_points[path_component.index])
            ->AppendPolylinePoints(*polyline.points);
        previous_path_component_index = component_i;
        break;
      case ComponentType::kQuadratic:
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = true,
        });
        reinterpret_cast<const QuadraticPathComponent*>(
            &path_points[path_component.index])
            ->AppendPolylinePoints(scale, *polyline.points);
        previous_path_component_index = component_i;
        break;
      case ComponentType::kCubic:
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = true,
        });
        reinterpret_cast<const CubicPathComponent*>(
            &path_points[path_component.index])
            ->AppendPolylinePoints(scale, *polyline.points);
        previous_path_component_index = component_i;
        break;
      case ComponentType::kContour:
        if (component_i == path_components.size() - 1) {
          // If the last component is a contour, that means it's an empty
          // contour, so skip it.
          continue;
        }
        end_contour();

        Vector2 start_direction = compute_contour_start_direction(component_i);
        const auto& contour = data_->contours[path_component.index];
        polyline.contours.push_back({.start_index = polyline.points->size(),
                                     .is_closed = contour.is_closed,
                                     .start_direction = start_direction,
                                     .components = poly_components});

        polyline.points->push_back(contour.destination);
        break;
    }
  }
  end_contour();
  return polyline;
}

std::optional<Rect> Path::GetBoundingBox() const {
  return data_->bounds;
}

std::optional<Rect> Path::GetTransformedBoundingBox(
    const Matrix& transform) const {
  auto bounds = GetBoundingBox();
  if (!bounds.has_value()) {
    return std::nullopt;
  }
  return bounds->TransformBounds(transform);
}

}  // namespace impeller
