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

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

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

    private:
        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;
    }

    // Adds the given RawPath to the end of this path, with an optional transform.
    // Returns an iterator at the beginning of the newly added geometry.
    Iter addPath(const RawPath&, const Mat2D* = nullptr);

    void pruneEmptySegments(Iter start);
    void pruneEmptySegments() { pruneEmptySegments(begin()); }

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

    // If there is not currently an open contour, this method opens a new contour at the current pen
    // location, or [0,0] if the path is empty. Otherwise it does nothing.
    void injectImplicitMoveIfNeeded();

private:
    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
