#include "rive/shapes/path.hpp"
#include "rive/math/circle_constant.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/cubic_vertex.hpp"
#include "rive/shapes/cubic_detached_vertex.hpp"
#include "rive/shapes/path_vertex.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/shapes/straight_vertex.hpp"
#include <cassert>

using namespace rive;

StatusCode Path::onAddedClean(CoreContext* context) {
    StatusCode code = Super::onAddedClean(context);
    if (code != StatusCode::Ok) {
        return code;
    }

    // Find the shape.
    for (auto currentParent = parent(); currentParent != nullptr;
         currentParent = currentParent->parent())
    {
        if (currentParent->is<Shape>()) {
            m_Shape = currentParent->as<Shape>();
            m_Shape->addPath(this);
            return StatusCode::Ok;
        }
    }

    return StatusCode::MissingObject;
}

void Path::buildDependencies() {
    Super::buildDependencies();
    // Make sure this is called once the shape has all of the paints added
    // (paints get added during the added cycle so buildDependencies is a good
    // time to do this.)
    m_CommandPath = m_Shape->makeCommandPath(PathSpace::Neither);
}

void Path::addVertex(PathVertex* vertex) { m_Vertices.push_back(vertex); }

const Mat2D& Path::pathTransform() const { return worldTransform(); }

void Path::buildPath(CommandPath& commandPath) const {
    commandPath.reset();
    
    const bool isClosed = isPathClosed();
    const std::vector<PathVertex*>& vertices = m_Vertices;

    auto length = vertices.size();
    if (length < 2) {
        return;
    }
    auto firstPoint = vertices[0];

    // Init out to translation
    float outX, outY;
    bool prevIsCubic;

    float startX, startY;
    float startInX, startInY;
    bool startIsCubic;

    if (firstPoint->is<CubicVertex>()) {
        auto cubic = firstPoint->as<CubicVertex>();
        startIsCubic = prevIsCubic = true;
        auto inPoint = cubic->renderIn();
        startInX = inPoint[0];
        startInY = inPoint[1];
        auto outPoint = cubic->renderOut();
        outX = outPoint[0];
        outY = outPoint[1];
        auto translation = cubic->renderTranslation();
        commandPath.moveTo(startX = translation[0], startY = translation[1]);
    } else {
        startIsCubic = prevIsCubic = false;
        auto point = *firstPoint->as<StraightVertex>();

        if (auto radius = point.radius(); radius > 0.0f) {
            auto prev = vertices[length - 1];

            Vec2D pos = point.renderTranslation();

            Vec2D toPrev =
                (prev->is<CubicVertex>() ? prev->as<CubicVertex>()->renderOut()
                                         : prev->renderTranslation()) -
                pos;

            auto toPrevLength = toPrev.length();
            toPrev[0] /= toPrevLength;
            toPrev[1] /= toPrevLength;

            auto next = vertices[1];

            Vec2D toNext =
                (next->is<CubicVertex>() ? next->as<CubicVertex>()->renderIn()
                                         : next->renderTranslation()) -
                pos;
            auto toNextLength = toNext.length();
            toNext[0] /= toNextLength;
            toNext[1] /= toNextLength;

            float renderRadius =
                std::min(toPrevLength, std::min(toNextLength, radius));

            Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
            commandPath.moveTo(startInX = startX = translation[0],
                               startInY = startY = translation[1]);

            Vec2D outPoint =
                Vec2D::scaleAndAdd(pos, toPrev, icircleConstant * renderRadius);
            Vec2D inPoint =
                Vec2D::scaleAndAdd(pos, toNext, icircleConstant * renderRadius);
            Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
            commandPath.cubicTo(outPoint[0],
                                outPoint[1],
                                inPoint[0],
                                inPoint[1],
                                outX = posNext[0],
                                outY = posNext[1]);
            prevIsCubic = false;
        } else {
            auto translation = point.renderTranslation();
            commandPath.moveTo(startInX = startX = outX = translation[0],
                               startInY = startY = outY = translation[1]);
        }
    }

    for (size_t i = 1; i < length; i++) {
        auto vertex = vertices[i];

        if (vertex->is<CubicVertex>()) {
            auto cubic = vertex->as<CubicVertex>();
            auto inPoint = cubic->renderIn();
            auto translation = cubic->renderTranslation();

            commandPath.cubicTo(outX,
                                outY,
                                inPoint[0],
                                inPoint[1],
                                translation[0],
                                translation[1]);

            prevIsCubic = true;
            auto outPoint = cubic->renderOut();
            outX = outPoint[0];
            outY = outPoint[1];
        } else {
            auto point = *vertex->as<StraightVertex>();
            Vec2D pos = point.renderTranslation();

            if (auto radius = point.radius(); radius > 0.0f) {
                Vec2D toPrev = Vec2D(outX, outY) - pos;
                auto toPrevLength = toPrev.length();
                toPrev[0] /= toPrevLength;
                toPrev[1] /= toPrevLength;

                auto next = vertices[(i + 1) % length];

                Vec2D toNext = (next->is<CubicVertex>()
                                    ? next->as<CubicVertex>()->renderIn()
                                    : next->renderTranslation()) -
                               pos;
                auto toNextLength = toNext.length();
                toNext[0] /= toNextLength;
                toNext[1] /= toNextLength;

                float renderRadius =
                    std::min(toPrevLength, std::min(toNextLength, radius));

                Vec2D translation =
                    Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
                if (prevIsCubic) {
                    commandPath.cubicTo(outX,
                                        outY,
                                        translation[0],
                                        translation[1],
                                        translation[0],
                                        translation[1]);
                } else {
                    commandPath.lineTo(translation[0], translation[1]);
                }

                Vec2D outPoint = Vec2D::scaleAndAdd(
                    pos, toPrev, icircleConstant * renderRadius);
                Vec2D inPoint = Vec2D::scaleAndAdd(
                    pos, toNext, icircleConstant * renderRadius);
                Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
                commandPath.cubicTo(outPoint[0],
                                    outPoint[1],
                                    inPoint[0],
                                    inPoint[1],
                                    outX = posNext[0],
                                    outY = posNext[1]);
                prevIsCubic = false;
            } else if (prevIsCubic) {
                float x = pos[0];
                float y = pos[1];
                commandPath.cubicTo(outX, outY, x, y, x, y);

                prevIsCubic = false;
                outX = x;
                outY = y;
            } else {
                commandPath.lineTo(outX = pos[0], outY = pos[1]);
            }
        }
    }
    if (isClosed) {
        if (prevIsCubic || startIsCubic) {
            commandPath.cubicTo(outX, outY, startInX, startInY, startX, startY);
        } else {
            commandPath.lineTo(startX, startY);
        }
        commandPath.close();
    }
}

void Path::markPathDirty() {
    addDirt(ComponentDirt::Path);
    if (m_Shape != nullptr) {
        m_Shape->pathChanged();
    }
}

void Path::onDirty(ComponentDirt value) {
    if (hasDirt(value, ComponentDirt::WorldTransform) && m_Shape != nullptr) {
        m_Shape->pathChanged();
    }
}

void Path::update(ComponentDirt value) {
    Super::update(value);

    assert(m_CommandPath != nullptr);
    if (hasDirt(value, ComponentDirt::Path)) {
        buildPath(*m_CommandPath);
    }
    // if (hasDirt(value, ComponentDirt::WorldTransform) && m_Shape != nullptr)
    // {
    // 	// Make sure the path composer has an opportunity to rebuild the path
    // 	// (this is why the composer depends on the shape and all its paths,
    // 	// ascertaning it updates after both)
    // 	m_Shape->pathChanged();
    // }
}

#ifdef ENABLE_QUERY_FLAT_VERTICES

class DisplayCubicVertex : public CubicVertex {
public:
    DisplayCubicVertex(const Vec2D& in,
                       const Vec2D& out,
                       const Vec2D& translation)

    {
        m_InPoint = in;
        m_OutPoint = out;
        m_InValid = true;
        m_OutValid = true;
        x(translation[0]);
        y(translation[1]);
    }

    void computeIn() override {}
    void computeOut() override {}
};

FlattenedPath* Path::makeFlat(bool transformToParent) {
    if (m_Vertices.empty()) {
        return nullptr;
    }

    // Path transform always puts the path into world space.
    auto transform = pathTransform();

    if (transformToParent && parent()->is<TransformComponent>()) {
        // Put the transform in parent space.
        auto world = parent()->as<TransformComponent>()->worldTransform();
        Mat2D inverseWorld;
        if (!Mat2D::invert(inverseWorld, world)) {
            inverseWorld = Mat2D();
        }
        transform = inverseWorld * transform;
    }

    FlattenedPath* flat = new FlattenedPath();
    auto length = m_Vertices.size();
    PathVertex* previous = isPathClosed() ? m_Vertices[length - 1] : nullptr;
    bool deletePrevious = false;
    for (size_t i = 0; i < length; i++) {
        auto vertex = m_Vertices[i];

        switch (vertex->coreType()) {
            case StraightVertex::typeKey: {
                auto point = *vertex->as<StraightVertex>();
                if (point.radius() > 0.0f &&
                    (isPathClosed() || (i != 0 && i != length - 1))) {
                    auto next = m_Vertices[(i + 1) % length];

                    Vec2D prevPoint =
                        previous->is<CubicVertex>()
                            ? previous->as<CubicVertex>()->renderOut()
                            : previous->renderTranslation();
                    Vec2D nextPoint = next->is<CubicVertex>()
                                          ? next->as<CubicVertex>()->renderIn()
                                          : next->renderTranslation();

                    Vec2D pos = point.renderTranslation();

                    Vec2D toPrev = prevPoint - pos;
                    auto toPrevLength = toPrev.length();
                    toPrev[0] /= toPrevLength;
                    toPrev[1] /= toPrevLength;

                    Vec2D toNext = nextPoint - pos;
                    auto toNextLength = toNext.length();
                    toNext[0] /= toNextLength;
                    toNext[1] /= toNextLength;

                    auto renderRadius = std::min(
                        toPrevLength, std::min(toNextLength, point.radius()));
                    Vec2D translation =
                        Vec2D::scaleAndAdd(pos, toPrev, renderRadius);

                    Vec2D out = Vec2D::scaleAndAdd(
                        pos, toPrev, icircleConstant * renderRadius);
                    {
                        auto v1 = new DisplayCubicVertex(
                            translation, out, translation);
                        flat->addVertex(v1, transform);
                        delete v1;
                    }

                    translation = Vec2D::scaleAndAdd(pos, toNext, renderRadius);

                    Vec2D in = Vec2D::scaleAndAdd(
                        pos, toNext, icircleConstant * renderRadius);
                    auto v2 =
                        new DisplayCubicVertex(in, translation, translation);

                    flat->addVertex(v2, transform);
                    if (deletePrevious) {
                        delete previous;
                    }
                    previous = v2;
                    deletePrevious = true;
                    break;
                }
            }
            default:
                if (deletePrevious) {
                    delete previous;
                }
                previous = vertex;
                deletePrevious = false;
                flat->addVertex(previous, transform);
                break;
        }
    }
    if (deletePrevious) {
        delete previous;
    }
    return flat;
}

void FlattenedPath::addVertex(PathVertex* vertex, const Mat2D& transform) {
    // To make this easy and relatively clean we just transform the vertices.
    // Requires the vertex to be passed in as a clone.
    if (vertex->is<CubicVertex>()) {
        auto cubic = vertex->as<CubicVertex>();

        // Cubics need to be transformed so we create a Display version which
        // has set in/out values.
        const auto in = transform * cubic->renderIn();
        const auto out = transform * cubic->renderOut();
        const auto translation = transform * cubic->renderTranslation();

        auto displayCubic = new DisplayCubicVertex(in, out, translation);
        m_Vertices.push_back(displayCubic);
    } else {
        auto point = new PathVertex();
        Vec2D translation = transform * vertex->renderTranslation();
        point->x(translation[0]);
        point->y(translation[1]);
        m_Vertices.push_back(point);
    }
}

FlattenedPath::~FlattenedPath() {
    for (auto vertex : m_Vertices) {
        delete vertex;
    }
}

#endif
