#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;
            Vec2D::subtract(toPrev,
                            prev->is<CubicVertex>()
                                ? prev->as<CubicVertex>()->renderOut()
                                : prev->renderTranslation(),
                            pos);
            auto toPrevLength = Vec2D::length(toPrev);
            toPrev[0] /= toPrevLength;
            toPrev[1] /= toPrevLength;

            auto next = vertices[1];

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

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

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

            Vec2D inPoint;
            Vec2D::scaleAndAdd(
                inPoint, pos, toNext, icircleConstant * renderRadius);

            Vec2D posNext;
            Vec2D::scaleAndAdd(posNext, 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::subtract(toPrev, Vec2D(outX, outY), pos);
                auto toPrevLength = Vec2D::length(toPrev);
                toPrev[0] /= toPrevLength;
                toPrev[1] /= toPrevLength;

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

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

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

                Vec2D translation;
                Vec2D::scaleAndAdd(translation, 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(
                    outPoint, pos, toPrev, icircleConstant * renderRadius);

                Vec2D inPoint;
                Vec2D::scaleAndAdd(
                    inPoint, pos, toNext, icircleConstant * renderRadius);

                Vec2D posNext;
                Vec2D::scaleAndAdd(posNext, 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;
                    Vec2D::subtract(toPrev, prevPoint, pos);
                    auto toPrevLength = Vec2D::length(toPrev);
                    toPrev[0] /= toPrevLength;
                    toPrev[1] /= toPrevLength;

                    Vec2D toNext;
                    Vec2D::subtract(toNext, nextPoint, pos);
                    auto toNextLength = Vec2D::length(toNext);
                    toNext[0] /= toNextLength;
                    toNext[1] /= toNextLength;

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

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

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

                    Vec2D in;
                    Vec2D::scaleAndAdd(
                        in, 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.
        Vec2D in, out, translation;
        Vec2D::transform(in, cubic->renderIn(), transform);
        Vec2D::transform(out, cubic->renderOut(), transform);
        Vec2D::transform(translation, cubic->renderTranslation(), transform);

        auto displayCubic = new DisplayCubicVertex(in, out, translation);
        m_Vertices.push_back(displayCubic);
    }
    else
    {
        auto point = new PathVertex();
        Vec2D translation;
        Vec2D::transform(translation, 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
