#include "rive/shapes/path.hpp"
#include "rive/shapes/points_path.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/cubic_vertex.hpp"
#include "rive/shapes/cubic_detached_vertex.hpp"
#include "rive/shapes/deformer.hpp"
#include "rive/shapes/path_vertex.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/shapes/straight_vertex.hpp"
#include "rive/math/math_types.hpp"
#include <algorithm>
#include <cassert>

using namespace rive;

/// Compute an ideal control point distance to create a curve of the given
/// radius. Based on "natural rounding"
/// https://observablehq.com/@daformat/rounding-polygon-corners
float Path::computeIdealControlPointDistance(const Vec2D& toPrev,
                                             const Vec2D& toNext,
                                             float radius)
{
    // Get the angle between next and prev
    float angle = fabs(
        std::atan2(Vec2D::cross(toPrev, toNext), Vec2D::dot(toPrev, toNext)));

    return fmin(radius,
                (4.0f / 3.0f) *
                    std::tan(math::PI / (2.0f * ((2.0f * math::PI) / angle))) *
                    radius *
                    (angle < math::PI / 2 ? 1 + std::cos(angle)
                                          : 2.0f - std::sin(angle)));
}

static void rotatePoints(const Vec2D& nextPoint,
                         const Vec2D& prevPoint,
                         const Vec2D& point,
                         Vec2D& outPoint,
                         Vec2D& inPoint)
{
    // Calculate angle between original pos and new positions
    auto v1 = prevPoint - nextPoint;
    auto v2 = point - nextPoint;
    float angle = std::atan2(Vec2D::cross(v1, v2), Vec2D::dot(v1, v2));
    {
        // Rotate outPoint around prevPoint twice the angle
        float s = std::sin(angle * 2);
        float c = std::cos(angle * 2);
        outPoint.x -= prevPoint.x;
        outPoint.y -= prevPoint.y;
        float xNew = outPoint.x * c - outPoint.y * s;
        float yNew = outPoint.x * s + outPoint.y * c;
        outPoint.x = xNew + prevPoint.x;
        outPoint.y = yNew + prevPoint.y;
    }
    {
        // Rotate inPoint around nextPoint twice the angle
        float s = std::sin(-angle * 2);
        float c = std::cos(-angle * 2);
        inPoint.x -= nextPoint.x;
        inPoint.y -= nextPoint.y;
        float xNew = inPoint.x * c - inPoint.y * s;
        float yNew = inPoint.x * s + inPoint.y * c;
        inPoint.x = xNew + nextPoint.x;
        inPoint.y = yNew + nextPoint.y;
    }
}

RenderPathDeformer* Path::deformer() const
{
    if (m_Shape != nullptr)
    {
        return m_Shape->deformer();
    }
    return nullptr;
}

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

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

void Path::popVertex() { m_Vertices.pop_back(); }

#ifdef WITH_RIVE_EDITOR
void Path::sortVerticesForEditor()
{
    auto byChildOrder = [](const PathVertex* a, const PathVertex* b) {
        return a->childOrder().compareTo(b->childOrder()) < 0;
    };
    if (std::is_sorted(m_Vertices.begin(), m_Vertices.end(), byChildOrder))
    {
        return;
    }
    std::sort(m_Vertices.begin(), m_Vertices.end(), byChildOrder);
    // A reorder after the path has built leaves m_rawPath on the old
    // vertex sequence.
    markPathDirty();
}
#endif

void Path::addFlags(PathFlags flags) { m_pathFlags |= flags; }
bool Path::isFlagged(PathFlags flags) const
{
    return (int)(m_pathFlags & flags) != 0x00;
}

bool Path::canDeferPathUpdate()
{
    if (m_Shape == nullptr)
    {
        return false;
    }
    // A path cannot defer its update if the shapes requires an update. Note the
    // nuance here where we track that the shape may be marked for follow path
    // (meaning all child paths need to follow path). This doesn't mean the
    // Shape is necessarily forced to update put the paths are, which is why we
    // explicitly also check the shape's path space.

    return m_Shape->canDeferPathUpdate() &&
           !m_Shape->isFlagged(PathFlags::followPath) &&
           !isFlagged(PathFlags::followPath | PathFlags::clipping);
}

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

AABB Path::localBounds() const { return m_rawPath.preciseBounds(); }

void Path::addRoundedRect(RawPath& rawPath,
                          const AABB& bounds,
                          float topLeft,
                          float topRight,
                          float bottomRight,
                          float bottomLeft)
{
    struct Corner
    {
        Vec2D pos;
        Vec2D toPrev;
        Vec2D toNext;
        float radius;
    };
    // toPrev/toNext are the unit vectors buildPath derives from the adjacent
    // vertices; for a rectangle they are the axes.
    const Corner corners[4] = {
        {{bounds.left(), bounds.top()}, {0.0f, 1.0f}, {1.0f, 0.0f}, topLeft},
        {{bounds.right(), bounds.top()}, {-1.0f, 0.0f}, {0.0f, 1.0f}, topRight},
        {{bounds.right(), bounds.bottom()},
         {0.0f, -1.0f},
         {-1.0f, 0.0f},
         bottomRight},
        {{bounds.left(), bounds.bottom()},
         {1.0f, 0.0f},
         {0.0f, -1.0f},
         bottomLeft},
    };
    // buildPath clamps a corner to half of each adjacent edge; a rectangle's
    // adjacent edges are its full width and height, so every corner shares one
    // limit.
    const float maxRadius = std::min(bounds.width(), bounds.height()) * 0.5f;

    Vec2D start;
    for (int i = 0; i < 4; i++)
    {
        const Corner& corner = corners[i];
        // Branch on the authored radius, as buildPath does: a radius under the
        // clamp still rounds, it just rounds by very little.
        if (corner.radius != 0.0f)
        {
            const float radius = std::min(std::abs(corner.radius), maxRadius);
            const float idealDistance =
                computeIdealControlPointDistance(corner.toPrev,
                                                 corner.toNext,
                                                 radius);
            const Vec2D enter =
                Vec2D::scaleAndAdd(corner.pos, corner.toPrev, radius);
            if (i == 0)
            {
                start = enter;
                rawPath.move(enter);
            }
            else
            {
                rawPath.line(enter);
            }
            Vec2D outPoint = Vec2D::scaleAndAdd(corner.pos,
                                                corner.toPrev,
                                                radius - idealDistance);
            Vec2D inPoint = Vec2D::scaleAndAdd(corner.pos,
                                               corner.toNext,
                                               radius - idealDistance);
            const Vec2D exit =
                Vec2D::scaleAndAdd(corner.pos, corner.toNext, radius);
            if (corner.radius < 0.0f)
            {
                rotatePoints(exit, enter, corner.pos, outPoint, inPoint);
            }
            rawPath.cubic(outPoint, inPoint, exit);
        }
        else if (i == 0)
        {
            start = corner.pos;
            rawPath.move(corner.pos);
        }
        else
        {
            rawPath.line(corner.pos);
        }
    }
    rawPath.line(start);
    rawPath.close();
}

void Path::buildPath(RawPath& rawPath) const
{
    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
    Vec2D out;
    bool prevIsCubic;

    Vec2D start, startIn;
    bool startIsCubic;

    if (firstPoint->is<CubicVertex>())
    {
        auto cubic = firstPoint->as<CubicVertex>();
        startIsCubic = prevIsCubic = true;
        startIn = cubic->renderIn();
        out = cubic->renderOut();
        start = cubic->renderTranslation();
        rawPath.move(start);
    }
    else
    {
        startIsCubic = prevIsCubic = false;
        auto point = *firstPoint->as<StraightVertex>();
        auto radius = point.radius();
        if (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.normalizeLength();

            auto next = vertices[1];

            Vec2D toNext =
                (next->is<CubicVertex>() ? next->as<CubicVertex>()->renderIn()
                                         : next->renderTranslation()) -
                pos;
            auto toNextLength = toNext.normalizeLength();

            float renderRadius = std::min(
                toPrevLength / 2.0f,
                std::min(toNextLength / 2.0f, radius > 0 ? radius : -radius));
            float idealDistance =
                Path::computeIdealControlPointDistance(toPrev,
                                                       toNext,
                                                       renderRadius);

            startIn = start = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
            rawPath.move(startIn);

            Vec2D outPoint =
                Vec2D::scaleAndAdd(pos, toPrev, renderRadius - idealDistance);
            Vec2D inPoint =
                Vec2D::scaleAndAdd(pos, toNext, renderRadius - idealDistance);
            out = Vec2D::scaleAndAdd(pos, toNext, renderRadius);

            if (radius < 0)
            {
                rotatePoints(out, startIn, pos, outPoint, inPoint);
            }
            rawPath.cubic(outPoint, inPoint, out);
            prevIsCubic = false;
        }
        else
        {
            startIn = start = out = point.renderTranslation();
            rawPath.move(out);
        }
    }

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

            rawPath.cubic(out, inPoint, translation);

            prevIsCubic = true;
            out = cubic->renderOut();
        }
        else
        {
            auto point = *vertex->as<StraightVertex>();
            Vec2D pos = point.renderTranslation();
            auto radius = point.radius();
            if (radius != 0.0f)
            {
                auto prev = vertices[i - 1];
                Vec2D toPrev = (prev->is<CubicVertex>()
                                    ? prev->as<CubicVertex>()->renderOut()
                                    : prev->renderTranslation()) -
                               pos;
                auto toPrevLength = toPrev.normalizeLength();

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

                Vec2D toNext = (next->is<CubicVertex>()
                                    ? next->as<CubicVertex>()->renderIn()
                                    : next->renderTranslation()) -
                               pos;
                auto toNextLength = toNext.normalizeLength();

                float renderRadius =
                    std::min(toPrevLength / 2.0f,
                             std::min(toNextLength / 2.0f,
                                      radius > 0 ? radius : -radius));
                float idealDistance =
                    computeIdealControlPointDistance(toPrev,
                                                     toNext,
                                                     renderRadius);

                Vec2D translation =
                    Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
                if (prevIsCubic)
                {
                    rawPath.cubic(out, translation, translation);
                }
                else
                {
                    rawPath.line(translation);
                }

                Vec2D outPoint =
                    Vec2D::scaleAndAdd(pos,
                                       toPrev,
                                       renderRadius - idealDistance);
                Vec2D inPoint =
                    Vec2D::scaleAndAdd(pos,
                                       toNext,
                                       renderRadius - idealDistance);
                out = Vec2D::scaleAndAdd(pos, toNext, renderRadius);

                if (radius < 0)
                {
                    rotatePoints(out, translation, pos, outPoint, inPoint);
                }
                rawPath.cubic(outPoint, inPoint, out);
                prevIsCubic = false;
            }
            else if (prevIsCubic)
            {
                rawPath.cubic(out, pos, pos);

                prevIsCubic = false;
                out = pos;
            }
            else
            {
                out = pos;
                rawPath.line(out);
            }
        }
    }
    if (isClosed)
    {
        if (prevIsCubic || startIsCubic)
        {
            rawPath.cubic(out, startIn, start);
        }
        else
        {
            rawPath.line(start);
        }
        rawPath.close();
    }

    RenderPathDeformer* pathDeformer = deformer();
    if (pathDeformer != nullptr)
    {
        Mat2D transform = pathTransform();
        Mat2D inverse = transform.invertOrIdentity();
        pathDeformer->deformLocalRenderPath(rawPath, transform, inverse);
    }
}

void Path::markPathDirty(bool sendToLayout)
{
    addDirt(ComponentDirt::Path);
    shapePathChanged();
}

// Dirt accumulates until update, so the shape only needs telling once per
// cycle.
void Path::shapePathChanged()
{
    if (m_shapeNotified || m_Shape == nullptr)
    {
        return;
    }
    m_shapeNotified = true;
    m_Shape->pathChanged();
}

void Path::onDirty(ComponentDirt value)
{
    if (hasDirt(value, ComponentDirt::WorldTransform | ComponentDirt::NSlicer))
    {
        shapePathChanged();
    }
    if (m_deferredPathDirt)
    {
        addDirt(ComponentDirt::Path);
    }
}

void Path::update(ComponentDirt value)
{
    m_shapeNotified = false;
    Super::update(value);

    bool pathChanged = hasDirt(value, ComponentDirt::Path);
    bool worldTransformChanged = hasDirt(value, ComponentDirt::WorldTransform);
    bool deformerChanged = hasDirt(value, ComponentDirt::NSlicer);

    if (pathChanged || deformerChanged ||
        (deformer() != nullptr && worldTransformChanged))
    {
        if (canDeferPathUpdate())
        {
            m_deferredPathDirt = true;
            return;
        }
        m_deferredPathDirt = false;
        // Build path doesn't explicitly rewind because we use it to concatenate
        // multiple built paths into a single command path (like the hit
        // tester).
        m_rawPath.rewind();
        buildPath(m_rawPath);
    }
    // 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();
    // }
}

void Path::isHoleChanged() { markPathDirty(); }

bool Path::collapse(bool value)
{
    bool changed = Super::collapse(value);
    if (changed && m_Shape != nullptr)
    {
        m_Shape->pathCollapseChanged();
    }

    return changed;
}

#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.x);
        y(translation.y);
    }

    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();
        transform = world.invertOrIdentity() * 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.normalizeLength();

                    Vec2D toNext = nextPoint - pos;
                    auto toNextLength = toNext.normalizeLength();

                    auto renderRadius =
                        std::min(toPrevLength / 2.0f,
                                 std::min(toNextLength / 2.0f, point.radius()));
                    float idealDistance =
                        computeIdealControlPointDistance(toPrev,
                                                         toNext,
                                                         renderRadius);
                    Vec2D translation =
                        Vec2D::scaleAndAdd(pos, toPrev, renderRadius);

                    Vec2D out =
                        Vec2D::scaleAndAdd(pos,
                                           toPrev,
                                           renderRadius - idealDistance);
                    {
                        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,
                                                  renderRadius - idealDistance);
                    auto v2 =
                        new DisplayCubicVertex(in, translation, translation);

                    flat->addVertex(v2, transform);
                    if (deletePrevious)
                    {
                        delete previous;
                    }
                    previous = v2;
                    deletePrevious = true;
                    break;
                }
                RIVE_FALLTHROUGH;
            }
            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.x);
        point->y(translation.y);
        m_Vertices.push_back(point);
    }
}

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

#endif
