#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) {
    hull[0] = Vec2D::lerp(from, fromOut, t);
    hull[1] = Vec2D::lerp(fromOut, toIn, t);
    hull[2] = Vec2D::lerp(toIn, to, t);

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

    hull[5] = Vec2D::lerp(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) {
    const Vec2D oneThird = Vec2D::lerp(from, to, 1.0f / 3.0f),
                twoThird = Vec2D::lerp(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++) {
        m_TransformedPoints[i] = transform * m_Points[i];
    }

    // 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 = to - from;
            if (moveTo) {
                Vec2D point = from + dir * startT;
                result->moveTo(point[0], point[1]);
            }
            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);
}
