#include "rive/shapes/metrics_path.hpp"
#include "rive/renderer.hpp"
#include <math.h>

using namespace rive;

float clamp(float v, float lo, float hi)
{
    if (v < lo)
    {
        return lo;
    }
    else if (v > hi)
    {
        return hi;
    }
    return v;
}

void MetricsPath::reset()
{
    m_ComputedLength = 0.0f;
    m_CubicSegments.clear();
    m_Points.clear();
    m_Parts.clear();
    m_Lengths.clear();
    m_Paths.clear();
}

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

void MetricsPath::moveTo(float x, float y)
{
    assert(m_Points.size() == 0);
    m_Points.emplace_back(Vec2D(x, y));
}

void MetricsPath::lineTo(float x, float y)
{
    m_Parts.push_back(PathPart(0, m_Points.size()));
    m_Points.emplace_back(Vec2D(x, y));
}

void MetricsPath::cubicTo(
    float ox, float oy, float ix, float iy, float x, float y)
{
    m_Parts.push_back(PathPart(1, m_Points.size()));
    m_Points.emplace_back(Vec2D(ox, oy));
    m_Points.emplace_back(Vec2D(ix, iy));
    m_Points.emplace_back(Vec2D(x, y));
}

void MetricsPath::close() {}

static void computeHull(const Vec2D& from,
                        const Vec2D& fromOut,
                        const Vec2D& toIn,
                        const Vec2D& to,
                        float t,
                        Vec2D* hull)
{
    Vec2D::lerp(hull[0], from, fromOut, t);
    Vec2D::lerp(hull[1], fromOut, toIn, t);
    Vec2D::lerp(hull[2], toIn, to, t);

    Vec2D::lerp(hull[3], hull[0], hull[1], t);
    Vec2D::lerp(hull[4], hull[1], hull[2], t);

    Vec2D::lerp(hull[5], hull[3], hull[4], t);
}

static const float minSegmentLength = 0.05f;
static const float distTooFar = 1.0f;

static bool tooFar(const Vec2D& a, const Vec2D& b)
{
    return std::max(std::abs(a[0] - b[0]), std::abs(a[1] - b[1])) > distTooFar;
}

static bool shouldSplitCubic(const Vec2D& from,
                             const Vec2D& fromOut,
                             const Vec2D& toIn,
                             const Vec2D& to)
{
    Vec2D oneThird, twoThird;
    Vec2D::lerp(oneThird, from, to, 1.0f / 3.0f);
    Vec2D::lerp(twoThird, from, to, 2.0f / 3.0f);
    return tooFar(fromOut, oneThird) || tooFar(toIn, twoThird);
}

static float segmentCubic(const Vec2D& from,
                          const Vec2D& fromOut,
                          const Vec2D& toIn,
                          const Vec2D& to,
                          float runningLength,
                          float t1,
                          float t2,
                          std::vector<CubicSegment>& segments)
{

    if (shouldSplitCubic(from, fromOut, toIn, to))
    {
        float halfT = (t1 + t2) / 2.0f;

        Vec2D hull[6];
        computeHull(from, fromOut, toIn, to, 0.5f, hull);

        runningLength = segmentCubic(from,
                                     hull[0],
                                     hull[3],
                                     hull[5],
                                     runningLength,
                                     t1,
                                     halfT,
                                     segments);
        runningLength = segmentCubic(
            hull[5], hull[4], hull[2], to, runningLength, halfT, t2, segments);
    }
    else
    {
        float length = Vec2D::distance(from, to);
        runningLength += length;
        if (length > minSegmentLength)
        {
            segments.emplace_back(CubicSegment(t2, runningLength));
        }
    }
    return runningLength;
}

float MetricsPath::computeLength(const Mat2D& transform)
{
    // If the pre-computed length is still valid (transformed with the same
    // transform) just return that.
    if (!m_Lengths.empty() && transform == m_ComputedLengthTransform)
    {
        return m_ComputedLength;
    }
    m_ComputedLengthTransform = transform;
    m_Lengths.clear();
    m_CubicSegments.clear();

    // We have to dupe the transformed points as we're not sure whether just the
    // transform is changing (path may not have been reset but got added with
    // another transform).
    m_TransformedPoints.resize(m_Points.size());
    for (size_t i = 0, l = m_Points.size(); i < l; i++)
    {
        Vec2D::transform(m_TransformedPoints[i], m_Points[i], transform);
    }

    // Should never have subPaths with more subPaths (Skia allows this but for
    // Rive this isn't necessary and it keeps things simpler).
    assert(m_Paths.empty());
    const Vec2D* pen = &m_TransformedPoints[0];
    int idx = 1;
    float length = 0.0f;

    for (PathPart& part : m_Parts)
    {
        switch (part.type)
        {
            case PathPart::line:
            {
                const Vec2D& point = m_TransformedPoints[idx++];

                float partLength = Vec2D::distance(*pen, point);
                m_Lengths.push_back(partLength);
                pen = &point;
                length += partLength;
                break;
            }
            // Anything above 0 is the number of cubic parts...
            default:
            {
                // Subdivide as necessary...

                // push in the parts

                const Vec2D& from = pen[0];
                const Vec2D& fromOut = pen[1];
                const Vec2D& toIn = pen[2];
                const Vec2D& to = pen[3];

                idx += 3;
                pen = &to;

                int index = (int)m_CubicSegments.size();
                part.type = index + 1;
                float partLength = segmentCubic(
                    from, fromOut, toIn, to, 0.0f, 0.0f, 1.0f, m_CubicSegments);
                m_Lengths.push_back(partLength);
                length += partLength;
                part.numSegments = m_CubicSegments.size() - index;
                break;
            }
        }
    }
    m_ComputedLength = length;
    return length;
}

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 (startLength == endLength)
    {
        // nothing to trim.
        return;
    }
    // We need to find the first part to trim.
    float length = 0.0f;

    int partCount = (int)m_Parts.size();
    int firstPartIndex = -1, lastPartIndex = partCount - 1;
    float startT = 0.0f, endT = 1.0f;
    // Find first part.
    for (int i = 0; i < partCount; i++)
    {
        float partLength = m_Lengths[i];
        if (length + partLength > startLength)
        {
            firstPartIndex = i;
            startT = (startLength - length) / partLength;
            break;
        }
        length += partLength;
    }
    if (firstPartIndex == -1)
    {
        // Couldn't find it.
        return;
    }

    // Find last part.
    for (int i = firstPartIndex; i < partCount; i++)
    {
        float partLength = m_Lengths[i];
        if (length + partLength >= endLength)
        {
            lastPartIndex = i;
            endT = (endLength - length) / partLength;
            break;
        }
        length += partLength;
    }

    // Lets make sur we're between 0 & 1f on both start & end.
    startT = clamp(startT, 0.0f, 1.0f);
    endT = clamp(endT, 0.0f, 1.0f);

    if (firstPartIndex == lastPartIndex)
    {
        extractSubPart(firstPartIndex, startT, endT, moveTo, result);
    }
    else
    {
        extractSubPart(firstPartIndex, startT, 1.0f, moveTo, result);
        for (int i = firstPartIndex + 1; i < lastPartIndex; i++)
        {
            // add entire part...
            const PathPart& part = m_Parts[i];
            switch (part.type)
            {
                case PathPart::line:
                {
                    const Vec2D& point = m_TransformedPoints[part.offset];
                    result->lineTo(point[0], point[1]);
                    break;
                }
                default:
                {
                    const Vec2D& point1 = m_TransformedPoints[part.offset];
                    const Vec2D& point2 = m_TransformedPoints[part.offset + 1];
                    const Vec2D& point3 = m_TransformedPoints[part.offset + 2];
                    result->cubicTo(point1[0],
                                    point1[1],
                                    point2[0],
                                    point2[1],
                                    point3[0],
                                    point3[1]);
                    break;
                }
            }
        }
        extractSubPart(lastPartIndex, 0.0f, endT, false, result);
    }
}

float lerp(float from, float to, float f) { return from + f * (to - from); }

void MetricsPath::extractSubPart(
    int index, float startT, float endT, bool moveTo, RenderPath* result)
{
    assert(startT >= 0.0f && startT <= 1.0f && endT >= 0.0f && endT <= 1.0f);
    const PathPart& part = m_Parts[index];
    switch (part.type)
    {
        case PathPart::line:
        {
            const Vec2D& from = m_TransformedPoints[part.offset - 1];
            const Vec2D& to = m_TransformedPoints[part.offset];
            Vec2D dir;
            Vec2D::subtract(dir, to, from);
            if (moveTo)
            {
                Vec2D point;
                Vec2D::scaleAndAdd(point, from, dir, startT);
                result->moveTo(point[0], point[1]);
            }
            Vec2D::scaleAndAdd(dir, from, dir, endT);
            result->lineTo(dir[0], dir[1]);

            break;
        }
        default:
        {
            auto startingSegmentIndex = part.type - 1;
            auto startEndSegmentIndex = startingSegmentIndex;
            auto endingSegmentIndex = startingSegmentIndex + part.numSegments;

            // Find cubicStartT and cubicEndT
            float length = m_Lengths[index];
            if (startT != 0.0f)
            {
                float startLength = startT * length;
                for (int si = startingSegmentIndex; si < endingSegmentIndex;
                     si++)
                {
                    const CubicSegment& segment = m_CubicSegments[si];
                    if (segment.length >= startLength)
                    {
                        if (si == startingSegmentIndex)
                        {
                            startT = segment.t * (startLength / segment.length);
                        }
                        else
                        {
                            float previousLength =
                                m_CubicSegments[si - 1].length;

                            float t = (startLength - previousLength) /
                                      (segment.length - previousLength);
                            startT =
                                lerp(m_CubicSegments[si - 1].t, segment.t, t);
                        }
                        // Help out the ending segment finder by setting its
                        // start to where we landed while finding the first
                        // segment, that way it can skip a bunch of work.
                        startEndSegmentIndex = si;
                        break;
                    }
                }
            }

            if (endT != 1.0f)
            {
                float endLength = endT * length;
                for (int si = startEndSegmentIndex; si < endingSegmentIndex;
                     si++)
                {
                    const CubicSegment& segment = m_CubicSegments[si];
                    if (segment.length >= endLength)
                    {
                        if (si == startingSegmentIndex)
                        {
                            endT = segment.t * (endLength / segment.length);
                        }
                        else
                        {
                            float previousLength =
                                m_CubicSegments[si - 1].length;

                            float t = (endLength - previousLength) /
                                      (segment.length - previousLength);
                            endT =
                                lerp(m_CubicSegments[si - 1].t, segment.t, t);
                        }
                        break;
                    }
                }
            }

            Vec2D hull[6];

            const Vec2D& from = m_TransformedPoints[part.offset - 1];
            const Vec2D& fromOut = m_TransformedPoints[part.offset];
            const Vec2D& toIn = m_TransformedPoints[part.offset + 1];
            const Vec2D& to = m_TransformedPoints[part.offset + 2];

            if (startT == 0.0f)
            {
                // Start is 0, so split at end and keep the left side.
                computeHull(from, fromOut, toIn, to, endT, hull);
                if (moveTo)
                {
                    result->moveTo(from[0], from[1]);
                }
                result->cubicTo(hull[0][0],
                                hull[0][1],
                                hull[3][0],
                                hull[3][1],
                                hull[5][0],
                                hull[5][1]);
            }
            else
            {
                // Split at start since it's non 0.
                computeHull(from, fromOut, toIn, to, startT, hull);
                if (moveTo)
                {
                    // Move to first point on the right side.
                    result->moveTo(hull[5][0], hull[5][1]);
                }
                if (endT == 1.0f)
                {
                    // End is 1, so no further split is necessary just cubicTo
                    // the remaining right side.
                    result->cubicTo(hull[4][0],
                                    hull[4][1],
                                    hull[2][0],
                                    hull[2][1],
                                    to[0],
                                    to[1]);
                }
                else
                {
                    // End is not 1, so split again and cubic to the left side
                    // of the split and remap endT to the new curve range
                    computeHull(hull[5],
                                hull[4],
                                hull[2],
                                to,
                                (endT - startT) / (1.0f - startT),
                                hull);

                    result->cubicTo(hull[0][0],
                                    hull[0][1],
                                    hull[3][0],
                                    hull[3][1],
                                    hull[5][0],
                                    hull[5][1]);
                }
            }
            break;
        }
    }
}

RenderMetricsPath::RenderMetricsPath() : m_RenderPath(makeRenderPath()) {}
RenderMetricsPath::~RenderMetricsPath() { delete m_RenderPath; }

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

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

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);
}
