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

#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();
  size_t count = 0u;
  for (const auto& component : data_->components) {
    if (component == 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() ||
         (data_->components.size() == 1 &&
          data_->components[0] == ComponentType::kContour);
}

/// Determine required storage for points and indices.
std::pair<size_t, size_t> Path::CountStorage(Scalar scale) const {
  size_t points = 0;
  size_t contours = 0;

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

  size_t storage_offset = 0u;
  for (size_t component_i = 0; component_i < path_components.size();
       component_i++) {
    const auto& path_component = path_components[component_i];
    switch (path_component) {
      case ComponentType::kLinear: {
        points += 2;
        break;
      }
      case ComponentType::kQuadratic: {
        const QuadraticPathComponent* quad =
            reinterpret_cast<const QuadraticPathComponent*>(
                &path_points[storage_offset]);
        points += quad->CountLinearPathComponents(scale);
        break;
      }
      case ComponentType::kCubic: {
        const CubicPathComponent* cubic =
            reinterpret_cast<const CubicPathComponent*>(
                &path_points[storage_offset]);
        points += cubic->CountLinearPathComponents(scale);
        break;
      }
      case Path::ComponentType::kContour:
        contours++;
    }
    storage_offset += VerbToOffset(path_component);
  }
  return std::make_pair(points, contours);
}

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;

  size_t storage_offset = 0u;
  for (size_t component_i = 0; component_i < path_components.size();
       component_i++) {
    const auto& path_component = path_components[component_i];
    switch (path_component) {
      case ComponentType::kLinear: {
        const LinearPathComponent* linear =
            reinterpret_cast<const LinearPathComponent*>(
                &path_points[storage_offset]);
        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[storage_offset]);
        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[storage_offset]);
        if (first_point) {
          writer.Write(cubic->p1);
          first_point = false;
        }
        cubic->ToLinearPathComponents(scale, writer);
        break;
      }
      case Path::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;
    }
    storage_offset += VerbToOffset(path_component);
  }
  if (started_contour) {
    writer.EndContour();
  }
}

bool Path::GetLinearComponentAtIndex(size_t index,
                                     LinearPathComponent& linear) const {
  auto& components = data_->components;
  if (index >= components.size() ||
      components[index] != ComponentType::kLinear) {
    return false;
  }

  size_t storage_offset = 0u;
  for (auto i = 0u; i < index; i++) {
    storage_offset += VerbToOffset(components[i]);
  }
  auto& points = data_->points;
  linear =
      LinearPathComponent(points[storage_offset], points[storage_offset + 1]);
  return true;
}

bool Path::GetQuadraticComponentAtIndex(
    size_t index,
    QuadraticPathComponent& quadratic) const {
  auto& components = data_->components;
  if (index >= components.size() ||
      components[index] != ComponentType::kQuadratic) {
    return false;
  }

  size_t storage_offset = 0u;
  for (auto i = 0u; i < index; i++) {
    storage_offset += VerbToOffset(components[i]);
  }
  auto& points = data_->points;

  quadratic =
      QuadraticPathComponent(points[storage_offset], points[storage_offset + 1],
                             points[storage_offset + 2]);
  return true;
}

bool Path::GetCubicComponentAtIndex(size_t index,
                                    CubicPathComponent& cubic) const {
  auto& components = data_->components;
  if (index >= components.size() ||
      components[index] != ComponentType::kCubic) {
    return false;
  }

  size_t storage_offset = 0u;
  for (auto i = 0u; i < index; i++) {
    storage_offset += VerbToOffset(components[i]);
  }
  auto& points = data_->points;

  cubic = CubicPathComponent(points[storage_offset], points[storage_offset + 1],
                             points[storage_offset + 2],
                             points[storage_offset + 3]);
  return true;
}

bool Path::GetContourComponentAtIndex(size_t index,
                                      ContourComponent& move) const {
  auto& components = data_->components;
  if (index >= components.size() ||
      components[index] != ComponentType::kContour) {
    return false;
  }

  size_t storage_offset = 0u;
  for (auto i = 0u; i < index; i++) {
    storage_offset += VerbToOffset(components[i]);
  }
  auto& points = data_->points;

  move = ContourComponent(points[storage_offset], points[storage_offset + 1]);
  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));
  }
}

void Path::EndContour(
    size_t storage_offset,
    Polyline& polyline,
    size_t component_index,
    std::vector<PolylineContour::Component>& poly_components) const {
  auto& path_components = data_->components;
  auto& path_points = data_->points;
  // Whenever a contour has ended, extract the exact end direction from
  // the last component.
  if (polyline.contours.empty() || component_index == 0) {
    return;
  }

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

  size_t previous_index = component_index - 1;
  storage_offset -= VerbToOffset(path_components[previous_index]);

  while (previous_index >= 0 && storage_offset >= 0) {
    const auto& path_component = path_components[previous_index];
    switch (path_component) {
      case ComponentType::kLinear: {
        auto* linear = reinterpret_cast<const LinearPathComponent*>(
            &path_points[storage_offset]);
        auto maybe_end = linear->GetEndDirection();
        if (maybe_end.has_value()) {
          contour.end_direction = maybe_end.value();
          return;
        }
        break;
      }
      case ComponentType::kQuadratic: {
        auto* quad = reinterpret_cast<const QuadraticPathComponent*>(
            &path_points[storage_offset]);
        auto maybe_end = quad->GetEndDirection();
        if (maybe_end.has_value()) {
          contour.end_direction = maybe_end.value();
          return;
        }
        break;
      }
      case ComponentType::kCubic: {
        auto* cubic = reinterpret_cast<const CubicPathComponent*>(
            &path_points[storage_offset]);
        auto maybe_end = cubic->GetEndDirection();
        if (maybe_end.has_value()) {
          contour.end_direction = maybe_end.value();
          return;
        }
        break;
      }
      case ComponentType::kContour: {
        // Hit previous contour, return.
        return;
      };
    }
    storage_offset -= VerbToOffset(path_component);
    previous_index--;
  }
};

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;
  std::optional<Vector2> start_direction;
  std::vector<PolylineContour::Component> poly_components;
  size_t storage_offset = 0u;
  size_t component_i = 0;

  for (; component_i < path_components.size(); component_i++) {
    auto path_component = path_components[component_i];
    switch (path_component) {
      case ComponentType::kLinear: {
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = false,
        });
        auto* linear = reinterpret_cast<const LinearPathComponent*>(
            &path_points[storage_offset]);
        linear->AppendPolylinePoints(*polyline.points);
        if (!start_direction.has_value()) {
          start_direction = linear->GetStartDirection();
        }
        break;
      }
      case ComponentType::kQuadratic: {
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = true,
        });
        auto* quad = reinterpret_cast<const QuadraticPathComponent*>(
            &path_points[storage_offset]);
        quad->AppendPolylinePoints(scale, *polyline.points);
        if (!start_direction.has_value()) {
          start_direction = quad->GetStartDirection();
        }
        break;
      }
      case ComponentType::kCubic: {
        poly_components.push_back({
            .component_start_index = polyline.points->size() - 1,
            .is_curve = true,
        });
        auto* cubic = reinterpret_cast<const CubicPathComponent*>(
            &path_points[storage_offset]);
        cubic->AppendPolylinePoints(scale, *polyline.points);
        if (!start_direction.has_value()) {
          start_direction = cubic->GetStartDirection();
        }
        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.
          break;
        }
        if (!polyline.contours.empty()) {
          polyline.contours.back().start_direction =
              start_direction.value_or(Vector2(0, -1));
          start_direction = std::nullopt;
        }
        EndContour(storage_offset, polyline, component_i, poly_components);

        auto* contour = reinterpret_cast<const ContourComponent*>(
            &path_points[storage_offset]);
        polyline.contours.push_back(PolylineContour{
            .start_index = polyline.points->size(),  //
            .is_closed = contour->IsClosed(),        //
            .start_direction = Vector2(0, -1),       //
            .components = poly_components            //
        });

        polyline.points->push_back(contour->destination);
        break;
    }
    storage_offset += VerbToOffset(path_component);
  }

  // Subtract the last storage offset increment so that the storage lookup is
  // correct, including potentially an empty contour as well.
  if (component_i > 0 && path_components.back() == ComponentType::kContour) {
    storage_offset -= VerbToOffset(ComponentType::kContour);
    component_i--;
  }

  if (!polyline.contours.empty()) {
    polyline.contours.back().start_direction =
        start_direction.value_or(Vector2(0, -1));
  }
  EndContour(storage_offset, polyline, component_i, poly_components);
  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
