#include "rive/artboard.hpp"
#include "rive/command_path.hpp"
#include "rive/constraints/constrainable_list.hpp"
#include "rive/constraints/follow_path_constraint.hpp"
#include "rive/factory.hpp"
#include "rive/math/contour_measure.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/transform_component.hpp"
#include <algorithm>
#include <iostream>
#include <typeinfo>

using namespace rive;

void FollowPathConstraint::distanceChanged() { markConstraintDirty(); }
void FollowPathConstraint::orientChanged() { markConstraintDirty(); }

const Mat2D FollowPathConstraint::targetTransform(float distanceOffset) const
{
    auto* tgt = target();
    if (tgt->is<Shape>() || tgt->is<Path>())
    {
        auto result = m_pathMeasure.atPercentage(distanceOffset);
        Vec2D position = result.pos;
        Mat2D transformB = Mat2D(tgt->worldTransform());

        if (orient())
        {
            auto componentsB = transformB.decompose();
            auto tangentRotation = std::atan2(result.tan.y, result.tan.x);
            float angleB = std::fmod(componentsB.rotation(), math::PI * 2);
            float diff = tangentRotation - angleB;
            if (diff > math::PI)
            {
                diff -= math::PI * 2;
            }
            else if (diff < -math::PI)
            {
                diff += math::PI * 2;
            }
            transformB = Mat2D::fromRotation(angleB + diff * strength());
        }
        Vec2D offsetPosition = Vec2D();
        if (offset())
        {
            if (parent()->is<TransformComponent>())
            {
                offsetPosition =
                    parent()->as<TransformComponent>()->composedTranslation();
            }
        }
        transformB[4] = position.x + offsetPosition.x;
        transformB[5] = position.y + offsetPosition.y;
        return transformB;
    }
    else
    {
        return tgt->worldTransform();
    }
}

void FollowPathConstraint::constrain(TransformComponent* component)
{
    auto* tgt = target();
    if (tgt == nullptr || tgt->isCollapsed())
    {
        return;
    }
    Mat2D transformB(targetTransform(distance()));
    const Mat2D& targetParentWorld = getParentWorld(*component);
    auto transformComponents = constrainHelper(component->worldTransform(),
                                               transformB,
                                               targetParentWorld);
    composeLandingAnchor(component, transformComponents, strength());
}

TransformComponents FollowPathConstraint::constrainHelper(
    const Mat2D& componentTransform,
    Mat2D& transformB,
    const Mat2D& componentParentWorld)
{
    const Mat2D& transformA = componentTransform;
    if (sourceSpace() == TransformSpace::local)
    {
        const Mat2D& targetParentWorld = getParentWorld(*target());

        Mat2D inverse;
        if (!targetParentWorld.invert(&inverse))
        {
            TransformComponents result;
            return result;
        }
        transformB = inverse * transformB;
    }
    if (destSpace() == TransformSpace::local)
    {
        transformB = componentParentWorld * transformB;
    }

    auto componentsA = transformA.decompose();
    auto componentsB = transformB.decompose();

    float t = strength();
    float ti = 1.0f - t;

    if (!orient())
    {
        float angleA = std::fmod(componentsA.rotation(), math::PI * 2);
        componentsB.rotation(angleA);
    }
    componentsB.x(componentsA.x() * ti + componentsB.x() * t);
    componentsB.y(componentsA.y() * ti + componentsB.y() * t);
    componentsB.scaleX(componentsA.scaleX());
    componentsB.scaleY(componentsA.scaleY());
    componentsB.skew(componentsA.skew());
    return componentsB;
}

void FollowPathConstraint::update(ComponentDirt value)
{
    auto* tgt = target();
    std::vector<Path*> paths;
    if (tgt->is<Shape>())
    {
        auto shape = tgt->as<Shape>();
        for (auto path : shape->paths())
        {
            paths.push_back(path);
        }
    }
    else if (tgt->is<Path>())
    {
        paths.push_back(tgt->as<Path>());
    }
    if (paths.size() > 0)
    {
        m_rawPath.rewind();
        for (auto path : paths)
        {
            m_rawPath.addPath(path->rawPath(), &path->pathTransform());
        }

        m_pathMeasure = PathMeasure(&m_rawPath);
    }
}

StatusCode FollowPathConstraint::onAddedClean(CoreContext* context)
{
    if (auto* tgt = target())
    {
        if (tgt->is<Shape>())
        {
            Shape* shape = static_cast<Shape*>(tgt);
            shape->addFlags(PathFlags::followPath);
        }
        else if (tgt->is<Path>())
        {
            Path* path = static_cast<Path*>(tgt);
            path->addFlags(PathFlags::followPath);
        }
    }
    return Super::onAddedClean(context);
}

void FollowPathConstraint::buildDependencies()
{
    // Read through `target()` so the editor build's dual-storage
    // (raw `m_Target` + `m_TargetHandle`) resolves through the
    // generational handle when it's set; runtime build inlines to
    // the raw pointer.
    auto* tgt = target();
    if (tgt != nullptr && tgt->is<Shape>())
    {
        // Follow path should update after the target's path composer.
        Shape* shape = static_cast<Shape*>(tgt);
        shape->pathComposer()->addDependent(this);
    }
    else if (tgt != nullptr && tgt->is<Path>())
    {
        Path* path = static_cast<Path*>(tgt);
        Shape* shape = path->shape();
        if (shape != nullptr)
        {
            shape->pathComposer()->addDependent(this);
        }
        else
        {
            path->addDependent(this);
        }
    }
    // The constrained component should update after follow path.
    addDependent(parent());
}
