#include "rive/shapes/metrics_path.hpp"
#include "rive/renderer.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/math/contour_measure.hpp"

using namespace rive;

void MetricsPath::rewind()
{
    m_Paths.clear();
    m_Contour.reset(nullptr);
    m_RawPath.rewind();
    m_ComputedLengthTransform = Mat2D();
    m_ComputedLength = 0;
}

void MetricsPath::addPath(CommandPath* path, const Mat2D& transform)
{
    MetricsPath* metricsPath = static_cast<MetricsPath*>(path);
    m_ComputedLength += metricsPath->computeLength(transform);
    m_Paths.emplace_back(metricsPath);
}

RawPath::Iter MetricsPath::addToRawPath(RawPath& rawPath, const Mat2D& transform) const
{
    return rawPath.addPath(m_RawPath, &transform);
}

void MetricsPath::moveTo(float x, float y)
{
    assert(m_RawPath.points().size() == 0);
    m_RawPath.move({x, y});
}

void MetricsPath::lineTo(float x, float y) { m_RawPath.line({x, y}); }

void MetricsPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
{
    m_RawPath.cubic({ox, oy}, {ix, iy}, {x, y});
}

void MetricsPath::close()
{
    // Should we pass the close() to our m_RawPath ???
}

float MetricsPath::computeLength(const Mat2D& transform)
{
    // Only compute if our pre-computed length is not valid
    if (!m_Contour || transform != m_ComputedLengthTransform)
    {
        m_ComputedLengthTransform = transform;
        m_Contour = ContourMeasureIter(m_RawPath * transform).next();
        m_ComputedLength = m_Contour ? m_Contour->length() : 0;
    }
    return m_ComputedLength;
}

void MetricsPath::trim(float startLength, float endLength, bool moveTo, RenderPath* result)
{
    assert(endLength >= startLength);
    if (!m_Paths.empty())
    {
        m_Paths.front()->trim(startLength, endLength, moveTo, result);
        return;
    }
    if (!m_Contour)
    {
        // All the contours were 0 length, so there's nothing to segment.
        return;
    }
    // TODO: if we can change the signature of MetricsPath and/or trim() to speak native
    //       rawpaths, we wouldn't need this temporary copy (since ContourMeasure speaks
    //       native rawpaths).
    RawPath tmp;
    m_Contour->getSegment(startLength, endLength, &tmp, moveTo);
    tmp.addTo(result);
}

RenderMetricsPath::RenderMetricsPath(rcp<RenderPath> path) : m_RenderPath(std::move(path)) {}

void RenderMetricsPath::addPath(CommandPath* path, const Mat2D& transform)
{
    MetricsPath::addPath(path, transform);
    m_RenderPath->addPath(path->renderPath(), transform);
}

void RenderMetricsPath::rewind()
{
    MetricsPath::rewind();
    m_RenderPath->rewind();
}

void RenderMetricsPath::moveTo(float x, float y)
{
    MetricsPath::moveTo(x, y);
    m_RenderPath->moveTo(x, y);
}

void RenderMetricsPath::lineTo(float x, float y)
{
    MetricsPath::lineTo(x, y);
    m_RenderPath->lineTo(x, y);
}

void RenderMetricsPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
{
    MetricsPath::cubicTo(ox, oy, ix, iy, x, y);
    m_RenderPath->cubicTo(ox, oy, ix, iy, x, y);
}

void RenderMetricsPath::close()
{
    MetricsPath::close();
    m_RenderPath->close();
}

void RenderMetricsPath::fillRule(FillRule value) { m_RenderPath->fillRule(value); }
