#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::onAddedDirty(CoreContext* context) {
    StatusCode code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok) {
        return code;
    }
    return StatusCode::Ok;
}

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)) {
            Mat2D::identity(inverseWorld);
        }
        Mat2D::multiply(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 = Vec2D::transform(cubic->renderIn(), transform);
        const auto out = Vec2D::transform(cubic->renderOut(), transform);
        const auto translation = Vec2D::transform(cubic->renderTranslation(), transform);

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

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

#endif
