/*
 * Copyright 2022 Rive
 */

#include "rive/core/type_conversions.hpp"
#include "rive/math/raw_path_utils.hpp"
#include "rive/math/contour_measure.hpp"
#include "rive/math/math_types.hpp"
#include <cmath>

using namespace rive;

enum SegmentType
{ // must fit in 2 bits
    kLine,
    kQuad,
    kCubic,
    // unused for now
};

/*
 *  Inspired by Skia's SkContourMeasure
 */

ContourMeasure::ContourMeasure(std::vector<Segment>&& segs,
                               std::vector<Vec2D>&& pts,
                               float length,
                               bool isClosed) :
    m_segments(std::move(segs)), m_points(std::move(pts)), m_length(length), m_isClosed(isClosed)
{}

// Return index of the segment that contains distance,
// or the last segment if distance == m_distance
size_t ContourMeasure::findSegment(float distance) const
{
    assert(m_segments.front().m_distance > 0);
    assert(m_segments.back().m_distance == m_length);

    assert(distance >= 0 && distance <= m_length);

    const Segment seg = {distance, 0, 0, 0};
    auto iter = std::lower_bound(m_segments.begin(), m_segments.end(), seg);
    assert(iter != m_segments.end());
    assert(iter->m_distance >= distance);
    assert(iter->m_ptIndex < m_points.size());
    return iter - m_segments.begin();
}

static ContourMeasure::PosTan eval_quad(const Vec2D pts[], float t)
{
    assert(t >= 0 && t <= 1);

    const EvalQuad eval(pts);

    // Compute derivative as at + b
    auto a = two(eval.a);
    auto b = eval.b;

    return {
        eval(t),
        (a * t + b).normalized(),
    };
}

static ContourMeasure::PosTan eval_cubic(const Vec2D pts[], float t)
{
    assert(t >= 0 && t <= 1);

    const EvalCubic eval(pts);

    // Compute derivative as at^2 + bt + c;
    auto a = eval.a * 3;
    auto b = two(eval.b);
    auto c = eval.c;

    return {
        eval(t),
        ((a * t + b) * t + c).normalized(),
    };
}

void ContourMeasure::Segment::extract(RawPath* dst, const Vec2D pts[]) const
{
    pts += m_ptIndex;
    switch (m_type)
    {
        case SegmentType::kLine:
            dst->line(pts[1]);
            break;
        case SegmentType::kQuad:
            dst->quad(pts[1], pts[2]);
            break;
        case SegmentType::kCubic:
            dst->cubic(pts[1], pts[2], pts[3]);
            break;
    }
}

void ContourMeasure::Segment::extract(RawPath* dst,
                                      float fromT,
                                      float toT,
                                      const Vec2D pts[],
                                      bool moveTo) const
{
    assert(fromT <= toT);
    pts += m_ptIndex;

    Vec2D tmp[4];
    switch (m_type)
    {
        case SegmentType::kLine:
            line_extract(pts, fromT, toT, tmp);
            if (moveTo)
            {
                dst->move(tmp[0]);
            }
            dst->line(tmp[1]);
            break;
        case SegmentType::kQuad:
            quad_extract(pts, fromT, toT, tmp);
            if (moveTo)
            {
                dst->move(tmp[0]);
            }
            dst->quad(tmp[1], tmp[2]);
            break;
        case SegmentType::kCubic:
            cubic_extract(pts, fromT, toT, tmp);
            if (moveTo)
            {
                dst->move(tmp[0]);
            }
            dst->cubic(tmp[1], tmp[2], tmp[3]);
            break;
    }
}

ContourMeasure::PosTan ContourMeasure::getPosTan(float distance) const
{
    // specal-case end of the contour
    if (distance >= m_length)
    {
        size_t N = m_points.size();
        assert(N > 1);
        return {m_points[N - 1], (m_points[N - 1] - m_points[N - 2]).normalized()};
    }

    if (distance < 0)
    {
        distance = 0;
    }

    size_t i = this->findSegment(distance);
    assert(i < m_segments.size());
    const auto seg = m_segments[i];
    const float currD = seg.m_distance;
    const float prevD = i > 0 ? m_segments[i - 1].m_distance : 0;

    assert(prevD < currD);
    assert(distance <= currD);
    assert(distance >= prevD);

    const float relD = (distance - prevD) / (currD - prevD);
    assert(relD >= 0 && relD <= 1);

    if (seg.m_type == SegmentType::kLine)
    {
        assert(seg.m_ptIndex + 1 < m_points.size());
        auto p0 = m_points[seg.m_ptIndex + 0];
        auto p1 = m_points[seg.m_ptIndex + 1];
        return {
            Vec2D::lerp(p0, p1, relD),
            (p1 - p0).normalized(),
        };
    }

    float prevT = 0;
    if (i > 0)
    {
        auto prev = m_segments[i - 1];
        if (prev.m_ptIndex == seg.m_ptIndex)
        {
            prevT = prev.getT();
        }
    }

    const float t = lerp(prevT, seg.getT(), relD);
    assert(t >= 0 && t <= 1);

    if (seg.m_type == SegmentType::kQuad)
    {
        assert(seg.m_ptIndex + 2 < m_points.size());
        return eval_quad(&m_points[seg.m_ptIndex], t);
    }
    else
    {
        assert(seg.m_type == SegmentType::kCubic);
        assert(seg.m_ptIndex + 3 < m_points.size());
        return eval_cubic(&m_points[seg.m_ptIndex], t);
    }
}

static const ContourMeasure::Segment* next_segment_beginning(const ContourMeasure::Segment* seg)
{
    auto startingPtIndex = seg->m_ptIndex;
    do
    {
        seg += 1;
    } while (seg->m_ptIndex == startingPtIndex);
    return seg;
}

// Compute the (interpolated) t for a distance within the index'th segment
static float compute_t(Span<const ContourMeasure::Segment> segs, size_t index, float distance)
{
    const auto seg = segs[index];
    assert(distance <= seg.m_distance);

    float prevDist = 0, prevT = 0;
    if (index > 0)
    {
        const auto prev = segs[index - 1];
        prevDist = prev.m_distance;
        if (prev.m_ptIndex == seg.m_ptIndex)
        {
            prevT = prev.getT();
        }
    }

    assert(prevDist < seg.m_distance);
    const auto ratio = (distance - prevDist) / (seg.m_distance - prevDist);
    return lerp(prevT, seg.getT(), ratio);
}

void ContourMeasure::getSegment(float startDist,
                                float endDist,
                                RawPath* dst,
                                bool startWithMove) const
{
    // sanitize the inputs
    startDist = std::max(0.f, startDist);
    endDist = std::min(m_length, endDist);
    if (startDist >= endDist)
    {
        return;
    }

    const auto startIndex = this->findSegment(startDist);
    const auto endIndex = this->findSegment(endDist);

    const auto start = m_segments[startIndex];
    const auto end = m_segments[endIndex];

    const auto startT = compute_t(m_segments, startIndex, startDist);
    const auto endT = compute_t(m_segments, endIndex, endDist);

    if (start.m_ptIndex == end.m_ptIndex)
    {
        start.extract(dst, startT, endT, m_points.data(), startWithMove);
    }
    else
    {
        start.extract(dst, startT, 1, m_points.data(), startWithMove);

        // now scoop up all the segments after start, and before end
        const auto* seg = next_segment_beginning(&m_segments[startIndex]);
        while (seg->m_ptIndex != end.m_ptIndex)
        {
            seg->extract(dst, m_points.data());
            seg = next_segment_beginning(seg);
        }
        assert(seg->m_ptIndex == end.m_ptIndex);

        end.extract(dst, 0, endT, m_points.data(), false);
    }
}

void ContourMeasure::dump() const
{
    printf("length %g pts %zu segs %zu\n", m_length, m_points.size(), m_segments.size());
    for (const auto& s : m_segments)
    {
        printf(" %g %d %g %d\n", s.m_distance, s.m_ptIndex, s.getT(), s.m_type);
    }
}

//////////////////////////////////////////////////////////////////////////////

constexpr auto kMaxDot30 = ContourMeasure::kMaxDot30;

static inline unsigned toDot30(float x)
{
    assert(x >= 0 && x < 1);
    return (unsigned)(x * (1 << 30));
}

static void addSeg(std::vector<ContourMeasure::Segment>& array,
                   const ContourMeasure::Segment& seg,
                   bool required = false)
{
    if (array.size() > 0)
    {
        const auto& last = array.back();
        assert(last.m_distance <= seg.m_distance);
        if (last.m_distance == seg.m_distance)
        {
            assert(!required);
            return;
        }
    }
    array.push_back(seg);
}

// These add[SegmentType]Segs routines append intermediate segments for the curve.
// They assume the caller has set the initial segment (with t == 0), so they only
// add intermediates.

float ContourMeasureIter::addQuadSegs(std::vector<ContourMeasure::Segment>& segs,
                                      const Vec2D pts[],
                                      uint32_t ptIndex,
                                      float distance) const
{
    const int count = computeApproximatingQuadLineSegments(pts, m_invTolerance);
    const float dt = 1.0f / count;
    const EvalQuad eval(pts);

    float t = dt;
    Vec2D prev = pts[0];
    for (int i = 1; i < count; ++i)
    {
        auto next = eval(t);
        distance += (next - prev).length();
        addSeg(segs, {distance, ptIndex, toDot30(t), SegmentType::kQuad});
        prev = next;
        t += dt;
    }
    distance += (pts[2] - prev).length();
    addSeg(segs, {distance, ptIndex, kMaxDot30, SegmentType::kQuad});
    return distance;
}

float ContourMeasureIter::addCubicSegs(std::vector<ContourMeasure::Segment>& segs,
                                       const Vec2D pts[],
                                       uint32_t ptIndex,
                                       float distance) const
{
    const int count = computeApproximatingCubicLineSegments(pts, m_invTolerance);
    const float dt = 1.0f / count;
    const EvalCubic eval(pts);

    float t = dt;
    Vec2D prev = pts[0];
    for (int i = 1; i < count; ++i)
    {
        auto next = eval(t);
        distance += (next - prev).length();
        addSeg(segs, {distance, ptIndex, toDot30(t), SegmentType::kCubic});
        prev = next;
        t += dt;
    }
    distance += (pts[3] - prev).length();
    addSeg(segs, {distance, ptIndex, kMaxDot30, SegmentType::kCubic});
    return distance;
}

void ContourMeasureIter::reset(const RawPath& path, float tolerance)
{
    m_iter = path.begin();
    m_end = path.end();
    m_srcPoints = path.points().data();

    constexpr float kMinTolerance = 1.0f / 16;
    m_invTolerance = 1.0f / std::max(tolerance, kMinTolerance);
}

// Can return null if either it encountered an empty contour (length == 0)
// or the iterator is exhausted.
//
rcp<ContourMeasure> ContourMeasureIter::tryNext()
{
    std::vector<ContourMeasure::Segment> segs;
    std::vector<Vec2D> pts;
    float distance = 0;
    bool isClosed = false;

    for (; m_iter != m_end; ++m_iter)
    {
        auto [verb, iterPts] = *m_iter;
        if (verb == PathVerb::move)
        {
            if (!pts.empty())
            {
                break; // We've alredy seen a move. Save this one for next time.
            }
            pts.push_back(iterPts[0]);
            continue;
        }
        assert(!pts.empty()); // PathVerb::move should have occurred first, and added a point.
        assert(!isClosed);    // PathVerb::close is always followed by a move or nothing.
        float prevDistance = distance;
        const uint32_t ptIndex = castTo<uint32_t>(pts.size() - 1);
        switch (verb)
        {
            case PathVerb::line:
                distance += (iterPts[1] - iterPts[0]).length();
                if (distance > prevDistance)
                {
                    addSeg(segs, {distance, ptIndex, kMaxDot30, SegmentType::kLine}, true);
                    pts.push_back(iterPts[1]);
                }
                break;
            case PathVerb::quad:
                distance = this->addQuadSegs(segs, iterPts, ptIndex, distance);
                if (distance > prevDistance)
                {
                    pts.push_back(iterPts[1]);
                    pts.push_back(iterPts[2]);
                }
                break;
            case PathVerb::cubic:
                distance = this->addCubicSegs(segs, iterPts, ptIndex, distance);
                if (distance > prevDistance)
                {
                    pts.push_back(iterPts[1]);
                    pts.push_back(iterPts[2]);
                    pts.push_back(iterPts[3]);
                }
                break;
            case PathVerb::close:
            {
                auto first = pts.front();
                distance += (first - iterPts[0]).length();
                if (distance > prevDistance)
                {
                    addSeg(segs, {distance, ptIndex, kMaxDot30, SegmentType::kLine}, true);
                    pts.push_back(first);
                }
                isClosed = true;
            }
            break;
            case PathVerb::move:
                RIVE_UNREACHABLE; // Handled above.
        }
    }

    if (distance == 0 || pts.size() < 2)
    {
        return nullptr;
    }
    return rcp<ContourMeasure>(
        new ContourMeasure(std::move(segs), std::move(pts), distance, isClosed));
}

rcp<ContourMeasure> ContourMeasureIter::next()
{
    rcp<ContourMeasure> cm;
    for (;;)
    {
        if ((cm = this->tryNext()))
        {
            break;
        }
        if (m_iter == m_end)
        {
            break;
        }
    }
    return cm;
}
