#include "rive/tess/tess_render_path.hpp"
#include "rive/tess/contour_stroke.hpp"
#include "tesselator.h"

static const float contourThreshold = 1.0f;

using namespace rive;
TessRenderPath::TessRenderPath() : m_segmentedContour(contourThreshold) {}
TessRenderPath::TessRenderPath(RawPath& rawPath, FillRule fillRule) :
    m_fillRule(fillRule), m_segmentedContour(contourThreshold) {
    m_rawPath.swap(rawPath);
}

TessRenderPath::~TessRenderPath() {}

void TessRenderPath::reset() {
    m_rawPath.rewind();
    m_subPaths.clear();
    m_isContourDirty = m_isTriangulationDirty = true;
}

void TessRenderPath::fillRule(FillRule value) { m_fillRule = value; }

void TessRenderPath::moveTo(float x, float y) { m_rawPath.moveTo(x, y); }
void TessRenderPath::lineTo(float x, float y) { m_rawPath.lineTo(x, y); }
void TessRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) {
    m_rawPath.cubicTo(ox, oy, ix, iy, x, y);
}
void TessRenderPath::close() {
    m_rawPath.close();
    m_isClosed = true;
}

void TessRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform) {
    m_subPaths.emplace_back(SubPath(path, transform));
}

const SegmentedContour& TessRenderPath::segmentedContour() const { return m_segmentedContour; }

// Helper for earcut to understand Vec2D
namespace mapbox {
namespace util {

template <> struct nth<0, Vec2D> {
    inline static auto get(const Vec2D& t) { return t.x; };
};
template <> struct nth<1, Vec2D> {
    inline static auto get(const Vec2D& t) { return t.y; };
};

} // namespace util
} // namespace mapbox

const RawPath& TessRenderPath::rawPath() const { return m_rawPath; }

void* stdAlloc(void* userData, unsigned int size) {
    int* allocated = (int*)userData;
    TESS_NOTUSED(userData);
    *allocated += (int)size;
    return malloc(size);
}

void stdFree(void* userData, void* ptr) {
    TESS_NOTUSED(userData);
    free(ptr);
}

bool TessRenderPath::triangulate() {
    if (!m_isTriangulationDirty) {
        return false;
    }
    m_isTriangulationDirty = false;
    triangulate(this);
    return true;
}

void TessRenderPath::triangulate(TessRenderPath* containerPath) {
    AABB bounds = AABB::forExpansion();
    // If there's a single path, we're going to try to assume the user isn't
    // doing any funky self overlapping winding and we'll try to triangulate it
    // quickly as a single polygon.
    if (m_subPaths.size() == 0) {
        if (!empty()) {
            Mat2D identity;
            contour(identity);

            bounds = m_segmentedContour.bounds();

            auto contour = m_segmentedContour.contourPoints();
            auto contours = Span(&contour, 1);
            m_earcut(contours);

            containerPath->addTriangles(contour, m_earcut.indices);
        }
    } else if (m_subPaths.size() == 1) {
        // We're a container but we only have 1 path, let's see if we can use
        // our fast triangulator.
        SubPath& subPath = m_subPaths.front();
        auto subRenderPath = static_cast<TessRenderPath*>(subPath.path());
        if (subRenderPath->isContainer()) {
            // Nope, subpath is also a container, keep going.
            subRenderPath->triangulate(containerPath);
        } else if (!subRenderPath->empty()) {
            // Yes, it's a single path with commands, triangulate it.
            subRenderPath->contour(subPath.transform());
            const SegmentedContour& segmentedContour = subRenderPath->segmentedContour();
            auto contour = segmentedContour.contourPoints();
            auto contours = Span(&contour, 1);
            m_earcut(contours);

            containerPath->addTriangles(contour, m_earcut.indices);
        }
    } else {
        // We're a container with multiple sub-paths.
        TESStesselator* tess = nullptr;
        for (SubPath& subPath : m_subPaths) {
            auto subRenderPath = static_cast<TessRenderPath*>(subPath.path());
            if (subRenderPath->isContainer()) {
                subRenderPath->triangulate(containerPath);
            } else if (!subRenderPath->empty()) {
                if (tess == nullptr) {
                    tess = tessNewTess(nullptr);
                }
                subRenderPath->contour(subPath.transform());
                const SegmentedContour& segmentedContour = subRenderPath->segmentedContour();
                auto contour = segmentedContour.contourPoints();
                tessAddContour(tess, 2, contour.data(), sizeof(float) * 2, contour.size());
                bounds.expand(segmentedContour.bounds());
            }
        }
        if (tess != nullptr) {
            if (tessTesselate(tess, TESS_WINDING_POSITIVE, TESS_POLYGONS, 3, 2, 0)) {
                auto verts = tessGetVertices(tess);
                // const int* vinds = tessGetVertexIndices(tess);
                auto nverts = tessGetVertexCount(tess);
                auto elems = tessGetElements(tess);
                auto nelems = tessGetElementCount(tess);

                std::vector<uint16_t> indices;
                for (int i = 0; i < nelems * 3; i++) {
                    indices.push_back(elems[i]);
                }

                containerPath->addTriangles(Span(reinterpret_cast<const Vec2D*>(verts), nverts),
                                            indices);
            }
            tessDeleteTess(tess);
        }
    }

    containerPath->setTriangulatedBounds(bounds);
}

void TessRenderPath::contour(const Mat2D& transform) {
    if (!m_isContourDirty && transform == m_contourTransform) {
        return;
    }

    m_isContourDirty = false;
    m_contourTransform = transform;
    m_segmentedContour.contour(m_rawPath, transform);
}

void TessRenderPath::extrudeStroke(ContourStroke* stroke,
                                   StrokeJoin join,
                                   StrokeCap cap,
                                   float strokeWidth,
                                   const Mat2D& transform) {
    if (isContainer()) {
        for (auto& subPath : m_subPaths) {
            static_cast<TessRenderPath*>(subPath.path())
                ->extrudeStroke(stroke, join, cap, strokeWidth, subPath.transform());
        }
        return;
    }

    contour(transform);

    stroke->extrude(&m_segmentedContour, m_isClosed, join, cap, strokeWidth);
}

bool TessRenderPath::empty() const { return m_rawPath.empty(); }
