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

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

} // namespace rive

#endif
