#include "rive/text/text_selection_path.hpp"
#include "rive/shapes/path.hpp"

using namespace rive;

// Crossing-number test of a point against a simple closed contour. The
// contours coming out of RectanglesToContour never touch each other, so
// probing with a vertex of another contour is safe.
static bool contourContains(const Contour& contour, Vec2D point)
{
  size_t size = contour.size();
  if (size < 3)
  {
    return false;
  }
  bool inside = false;
  for (size_t i = 0, j = size - 1; i < size; j = i++)
  {
    Vec2D a = contour.point(i);
    Vec2D b = contour.point(j);
    if ((a.y > point.y) != (b.y > point.y) &&
        point.x < (b.x - a.x) * (point.y - a.y) / (b.y - a.y) + a.x)
    {
      inside = !inside;
    }
  }
  return inside;
}

void TextSelectionPath::update(Span<AABB> rects, float cornerRadius)
{
  rewind();
  m_rectanglesToContour.reset();
  for (const AABB& rect : rects)
  {
    m_rectanglesToContour.addRect(rect);
  }
  m_rectanglesToContour.computeContours();

  RawPath& rawPath = *mutableRawPath();
  size_t count = m_rectanglesToContour.contourCount();
  for (size_t i = 0; i < count; i++)
  {
    Contour contour = m_rectanglesToContour.contour(i);
    if (contour.size() < 2)
    {
      continue;
    }
    // Wind outer contours clockwise and holes counter-clockwise so the
    // geometry reads the same under the clockwise, non-zero and even-odd
    // fill rules. Feathered fills are only drawn when the path is
    // clockwise, so this is what lets a feather apply here at all.
    Vec2D probe = contour.point(0);
    size_t depth = 0;
    for (size_t j = 0; j < count; j++)
    {
      if (j != i && contourContains(m_rectanglesToContour.contour(j), probe))
      {
        depth++;
      }
    }
    addRoundedPath(contour, cornerRadius, rawPath, (depth & 1) == 0);
  }
}

void TextSelectionPath::addRoundedPath(
    const Contour& contour,
    float radius,
    RawPath& rawPath,
    bool clockwise)
{
  bool reversed = contour.isClockwise() != clockwise;
  size_t length = contour.size();
  if (length < 2)
  {
    return;
  }

  Vec2D firstPoint = contour.point(0, reversed);
  Vec2D point = firstPoint;

  if (radius > 0.0f)
  {
    Vec2D prev = contour.point(length - 1, reversed);
    Vec2D pos = point;

    Vec2D toPrev = prev - pos;
    float toPrevLength = toPrev.length();
    toPrev.x /= toPrevLength;
    toPrev.y /= toPrevLength;

    Vec2D next = contour.point(1, reversed);

    Vec2D toNext = next - pos;
    float toNextLength = toNext.length();
    toNext.x /= toNextLength;
    toNext.y /= toNextLength;

    float renderRadius = std::min(
        toPrevLength / 2.0f,
        std::min(toNextLength / 2.0f, radius));
    float idealDistance = Path::computeIdealControlPointDistance(
        toPrev,
        toNext,
        renderRadius);

    Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
    rawPath.moveTo(translation.x, translation.y);

    Vec2D outPoint = Vec2D::scaleAndAdd(
        pos,
        toPrev,
        renderRadius - idealDistance);

    Vec2D inPoint = Vec2D::scaleAndAdd(
        pos,
        toNext,
        renderRadius - idealDistance);

    Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
    rawPath.cubicTo(
        outPoint.x,
        outPoint.y,
        inPoint.x,
        inPoint.y,
        posNext.x,
        posNext.y);
  }
  else
  {
    rawPath.moveTo(point.x, point.y);
  }

  for (size_t i = 1; i < length; i++)
  {
    Vec2D point = contour.point(i, reversed);

    if (radius > 0.0f)
    {
      Vec2D prev = contour.point(i - 1, reversed);

      Vec2D pos = point;
      Vec2D toPrev = prev - pos;

      float toPrevLength = toPrev.length();
      toPrev.x /= toPrevLength;
      toPrev.y /= toPrevLength;

      Vec2D next = contour.point((i + 1) % length, reversed);

      Vec2D toNext = next - pos;
      float toNextLength = toNext.length();
      toNext.x /= toNextLength;
      toNext.y /= toNextLength;

      float renderRadius = std::min(
          toPrevLength / 2.0f,
          std::min(toNextLength / 2.0f, radius));

      float idealDistance = Path::computeIdealControlPointDistance(
          toPrev,
          toNext,
          renderRadius);

      Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);

      rawPath.lineTo(translation.x, translation.y);

      Vec2D outPoint = Vec2D::scaleAndAdd(
          pos,
          toPrev,
          renderRadius - idealDistance);

      Vec2D inPoint = Vec2D::scaleAndAdd(
          pos,
          toNext,
          renderRadius - idealDistance);

      Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
      rawPath.cubicTo(
          outPoint.x,
          outPoint.y,
          inPoint.x,
          inPoint.y,
          posNext.x,
          posNext.y);
    }
    else
    {
      rawPath.lineTo(point.x, point.y);
    }
  }
  rawPath.close();
}