#include "rive/constraints/rotation_constraint.hpp"
#include "rive/transform_component.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"

using namespace rive;

void RotationConstraint::constrain(TransformComponent* component) {
    const Mat2D& transformA = component->worldTransform();
    Mat2D transformB;
    m_ComponentsA = transformA.decompose();
    if (m_Target == nullptr) {
        transformB = transformA;
        m_ComponentsB = m_ComponentsA;
    } else {
        transformB = m_Target->worldTransform();
        if (sourceSpace() == TransformSpace::local) {
            Mat2D inverse;

            if (!getParentWorld(*m_Target).invert(&inverse)) {
                return;
            }
            transformB = inverse * transformB;
        }

        m_ComponentsB = transformB.decompose();

        if (!doesCopy()) {
            m_ComponentsB.rotation(destSpace() == TransformSpace::local ? 0.0f
                                                                        : m_ComponentsA.rotation());
        } else {
            m_ComponentsB.rotation(m_ComponentsB.rotation() * copyFactor());
            if (offset()) {
                m_ComponentsB.rotation(m_ComponentsB.rotation() + component->rotation());
            }
        }

        if (destSpace() == TransformSpace::local) {
            // Destination space is in parent transform coordinates. Recompose
            // the parent local transform and get it in world, then decompose
            // the world for interpolation.

            transformB = Mat2D::compose(m_ComponentsB);
            transformB = getParentWorld(*component) * transformB;
            m_ComponentsB = transformB.decompose();
        }
    }
    bool clampLocal = minMaxSpace() == TransformSpace::local;
    if (clampLocal) {
        // Apply min max in local space, so transform to local coordinates
        // first.
        transformB = Mat2D::compose(m_ComponentsB);
        Mat2D inverse;
        if (!getParentWorld(*component).invert(&inverse)) {
            return;
        }
        m_ComponentsB = (inverse * transformB).decompose();
    }
    if (max() && m_ComponentsB.rotation() > maxValue()) {
        m_ComponentsB.rotation(maxValue());
    }
    if (min() && m_ComponentsB.rotation() < minValue()) {
        m_ComponentsB.rotation(minValue());
    }
    if (clampLocal) {
        // Transform back to world.
        transformB = Mat2D::compose(m_ComponentsB);
        transformB = getParentWorld(*component) * transformB;
        m_ComponentsB = transformB.decompose();
    }

    float angleA = std::fmod(m_ComponentsA.rotation(), math::PI * 2);
    float angleB = std::fmod(m_ComponentsB.rotation(), math::PI * 2);
    float diff = angleB - angleA;

    if (diff > math::PI) {
        diff -= math::PI * 2;
    } else if (diff < -math::PI) {
        diff += math::PI * 2;
    }

    m_ComponentsB.rotation(m_ComponentsA.rotation() + diff * strength());
    m_ComponentsB.x(m_ComponentsA.x());
    m_ComponentsB.y(m_ComponentsA.y());
    m_ComponentsB.scaleX(m_ComponentsA.scaleX());
    m_ComponentsB.scaleY(m_ComponentsA.scaleY());
    m_ComponentsB.skew(m_ComponentsA.skew());

    component->mutableWorldTransform() = Mat2D::compose(m_ComponentsB);
}
