/*
 * 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 <vector>

namespace rive {

class CommandPath;

class RawPath {
public:
    std::vector<Vec2D> m_Points;
    std::vector<PathVerb> m_Verbs;

    // Construct a RawPath from count points and verbs.
    RawPath(const Vec2D* points,
            std::size_t pointCount,
            const PathVerb* verbs,
            std::size_t verbCount);
    RawPath() {}
    ~RawPath() {}

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

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

    class Iter {
        const Vec2D* m_currPts;
        const PathVerb* m_currVerb;
        const PathVerb* m_stopVerb; // 1 past last verb
    public:
        Iter() : m_currPts(nullptr), m_currVerb(nullptr), m_stopVerb(nullptr) {}
        Iter(const RawPath& path) { this->reset(path); }

        void reset(const RawPath& path) {
            m_currPts = path.m_Points.data();
            m_currVerb = path.m_Verbs.data();
            m_stopVerb = path.m_Verbs.data() + path.m_Verbs.size();
        }

        // returns true iff next() will return false
        bool isDone() const { return m_currVerb >= m_stopVerb; }

        struct Rec {
            const Vec2D* pts;
            int count;
            PathVerb verb;

            operator bool() const { return pts != nullptr; }
        };
        Rec next();

        void backUp();
    };

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

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

} // namespace rive

#endif
