#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);
        m_geometryVersion++;
    }
    // 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
