/*
 * 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;
        }
        // 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
