/*
 * Copyright 2022 Rive
 */

#ifndef _RIVE_RAW_PATH_HPP_
#define _RIVE_RAW_PATH_HPP_

#include "rive/span.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/math/path_types.hpp"
#include "rive/math/vec2d.hpp"

#include <cmath>
#include <stdio.h>
#include <cstdint>
#include <tuple>
#include <vector>

namespace rive
{

class CommandPath;

class RawPath
{
public:
    bool operator==(const RawPath& o) const;
    bool operator!=(const RawPath& o) const { return !(*this == o); }

    bool empty() const { return m_Points.empty(); }
    AABB bounds() const;

    void move(Vec2D);
    void line(Vec2D);
    void quad(Vec2D, Vec2D);
    void cubic(Vec2D, Vec2D, Vec2D);
    void close();

    void swap(RawPath&);

    // Makes the path empty and frees any memory allocated by the drawing
    // (line, curve, move, close) calls.
    void reset();

    // Makes the path empty but keeps the memory for the drawing calls reserved.
    void rewind();

    RawPath transform(const Mat2D&) const;
    void transformInPlace(const Mat2D&);
    RawPath operator*(const Mat2D& mat) const { return this->transform(mat); }

    Span<const Vec2D> points() const { return m_Points; }
    Span<Vec2D> points() { return m_Points; }

    Span<const PathVerb> verbs() const { return m_Verbs; }
    Span<PathVerb> verbs() { return m_Verbs; }

    Span<const uint8_t> verbsU8() const
    {
        const uint8_t* ptr = (const uint8_t*)m_Verbs.data();
        return Span<const uint8_t>(ptr, m_Verbs.size());
    }

    // Syntactic sugar for x,y -vs- vec2d

    void moveTo(float x, float y) { move({x, y}); }
    void lineTo(float x, float y) { line({x, y}); }
    void quadTo(float x, float y, float x1, float y1) { quad({x, y}, {x1, y1}); }
    void cubicTo(float x, float y, float x1, float y1, float x2, float y2)
    {
        cubic({x, y}, {x1, y1}, {x2, y2});
    }

    // Helpers for adding new contours

    void addRect(const AABB&, PathDirection = PathDirection::cw);
    void addOval(const AABB&, PathDirection = PathDirection::cw);
    void addPoly(Span<const Vec2D>, bool isClosed);

    void addPath(const RawPath&, const Mat2D* = nullptr);

    // Simple STL-style iterator. To traverse using range-for:
    //
    //   for (auto [verb, pts] : rawPath) { ... }
    //
    class Iter
    {
    public:
        Iter() = default;
        Iter(const PathVerb* verbs, const Vec2D* pts) : m_verbs(verbs), m_pts(pts) {}

        bool operator!=(const Iter& that) const
        {
            assert(m_verbs != that.m_verbs || m_pts == that.m_pts);
            return m_verbs != that.m_verbs;
        }
        bool operator==(const Iter& that) const
        {
            assert(m_verbs != that.m_verbs || m_pts == that.m_pts);
            return m_verbs == that.m_verbs;
        }

        // Generic accessors. The points pointer is adjusted to point to p0 for each specific verb.
        PathVerb verb() const { return *m_verbs; }
        const Vec2D* pts() const { return m_pts + PtsBacksetForVerb(verb()); }
        std::tuple<PathVerb, const Vec2D*> operator*() const
        {
            PathVerb verb = *m_verbs;
            return {verb, m_pts + PtsBacksetForVerb(verb)};
        }

        // Specific point accessors for callers who already know the verb. (These may be a tiny bit
        // faster in some cases since the iterator doesn't have to check the verb.)
        Vec2D movePt() const
        {
            assert(verb() == PathVerb::move);
            return m_pts[0];
        }
        const Vec2D* linePts() const
        {
            assert(verb() == PathVerb::line);
            return m_pts - 1;
        }
        const Vec2D* quadPts() const
        {
            assert(verb() == PathVerb::quad);
            return m_pts - 1;
        }
        const Vec2D* cubicPts() const
        {
            assert(verb() == PathVerb::cubic);
            return m_pts - 1;
        }
        Vec2D ptBeforeClose() const
        {
            assert(verb() == PathVerb::close);
            return m_pts[-1];
        }
        // P0 for a close can be accessed via rawPtsPtr()[-1]. Note than p1 for a close is not in
        // the array at this location.

        // Internal pointers held by the iterator. See PtsBacksetForVerb() for how pts() relates to
        // the data for specific verbs.
        const PathVerb* rawVerbsPtr() const { return m_verbs; }
        const Vec2D* rawPtsPtr() const { return m_pts; }

        Iter& operator++() // "++iter"
        {
            m_pts += PtsAdvanceAfterVerb(*m_verbs++);
            return *this;
        }

    private:
        // How much should we advance pts after encountering this verb?
        inline static int PtsAdvanceAfterVerb(PathVerb verb)
        {
            switch (verb)
            {
                case PathVerb::move:
                    return 1;
                case PathVerb::line:
                    return 1;
                case PathVerb::quad:
                    return 2;
                case PathVerb::cubic:
                    return 3;
                case PathVerb::close:
                    return 0;
            }
            RIVE_UNREACHABLE();
        }

        // Where is p0 relative to our m_pts pointer? We find the start point of segments by
        // peeking backwards from the current point, which works as long as there is always a
        // PathVerb::move before any geometry. (injectImplicitMoveToIfNeeded() guarantees this
        // to be the case.)
        inline static int PtsBacksetForVerb(PathVerb verb)
        {
            switch (verb)
            {
                case PathVerb::move:
                    return 0;
                case PathVerb::line:
                    return -1;
                case PathVerb::quad:
                    return -1;
                case PathVerb::cubic:
                    return -1;
                case PathVerb::close:
                    return -1;
            }
            RIVE_UNREACHABLE();
        }

        const PathVerb* m_verbs;
        const Vec2D* m_pts;
    };
    Iter begin() const { return {m_Verbs.data(), m_Points.data()}; }
    Iter end() const
    {
        return {m_Verbs.data() + m_Verbs.size(), m_Points.data() + m_Points.size()};
    }

    template <typename Handler> RawPath morph(Handler proc) const
    {
        RawPath dst;
        // todo: dst.reserve(src.ptCount, src.verbCount);
        for (auto iter : *this)
        {
            PathVerb verb = std::get<0>(iter);
            const Vec2D* pts = std::get<1>(iter);
            switch (verb)
            {
                case PathVerb::move:
                    dst.move(proc(pts[0]));
                    break;
                case PathVerb::line:
                    dst.line(proc(pts[1]));
                    break;
                case PathVerb::quad:
                    dst.quad(proc(pts[1]), proc(pts[2]));
                    break;
                case PathVerb::cubic:
                    dst.cubic(proc(pts[1]), proc(pts[2]), proc(pts[3]));
                    break;
                case PathVerb::close:
                    dst.close();
                    break;
            }
        }
        return dst;
    }

    // Utility for pouring a RawPath into a CommandPath
    void addTo(CommandPath*) const;

private:
    void injectImplicitMoveIfNeeded();

    std::vector<Vec2D> m_Points;
    std::vector<PathVerb> m_Verbs;
    size_t m_lastMoveIdx;
    // True of the path is nonempty and the most recent verb is not "close".
    bool m_contourIsOpen = false;
};

} // namespace rive

#endif
