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

Path::~Path() { delete m_CommandPath; }

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

static void buildPath(CommandPath& commandPath,
                      bool isClosed,
                      const std::vector<PathVertex*>& vertices) {
    commandPath.reset();

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