#include "rive/constraints/ik_constraint.hpp"
#include "rive/bones/bone.hpp"
#include "rive/artboard.hpp"
#include <algorithm>
#include <math.h> // M_PI

using namespace rive;

void IKConstraint::buildDependencies() {
    Super::buildDependencies();

    // IK Constraint needs to depend on the target so that world transform
    // changes can propagate to the bones (and they can be reset before IK
    // runs).
    if (m_Target != nullptr) {
        m_Target->addDependent(this);
    }
}

StatusCode IKConstraint::onAddedClean(CoreContext* context) {
    if (!parent()->is<Bone>()) {
        return StatusCode::InvalidObject;
    }

    auto boneCount = parentBoneCount();
    auto bone = parent()->as<Bone>();
    std::vector<Bone*> bones;
    bones.push_back(bone);
    // Get the reverse FK chain of bones (from tip up).
    while (bone->parent()->is<Bone>() && boneCount > 0) {
        boneCount--;
        bone = bone->parent()->as<Bone>();
        bone->addPeerConstraint(this);
        bones.push_back(bone);
    }
    int numBones = (int)bones.size();
    m_FkChain.resize(numBones);
    // Now put them in FK order (top to bottom).
    int idx = 0;
    for (auto boneItr = bones.rbegin(); boneItr != bones.rend(); ++boneItr) {
        BoneChainLink& link = m_FkChain[idx];
        link.index = idx++;
        link.bone = *boneItr;
        link.angle = 0.0f;
    }

    // Make sure all of the first level children of each bone depend on the
    // tip (constrainedComponent).
    auto tip = parent()->as<Bone>();

    auto artboard = static_cast<Artboard*>(context);

    // Find all children of this bone (we don't directly build up
    // hierarchy at runtime, so we have to traverse everything and check
    // parents).
    for (auto core : artboard->objects()) {
        if (core == nullptr || !core->is<TransformComponent>()) {
            continue;
        }
        auto transformComponent = core->as<TransformComponent>();

        for (int i = 1; i < numBones; i++) {
            auto bone = bones[i];
            if (transformComponent->parent() == bone &&
                std::find(bones.begin(), bones.end(), transformComponent) == bones.end())
            {
                tip->addDependent(transformComponent);
            }
        }
    }
    return Super::onAddedClean(context);
}

void IKConstraint::markConstraintDirty() {
    Super::markConstraintDirty();
    // We automatically propagate dirt to the parent constrained bone, but we
    // also need to make sure the other bones we influence above it rebuild
    // their transforms.
    for (int i = 0, length = (int)m_FkChain.size() - 1; i < length; i++) {
        m_FkChain[i].bone->markTransformDirty();
    }
}

void IKConstraint::solve1(BoneChainLink* fk1, const Vec2D& worldTargetTranslation) {
    Mat2D iworld = fk1->parentWorldInverse;
    Vec2D pA;
    fk1->bone->worldTranslation(pA);
    Vec2D pBT(worldTargetTranslation);

    // To target in worldspace
    const Vec2D toTarget = pBT - pA;

    // Note this is directional, hence not transformMat2d
    Vec2D toTargetLocal = Vec2D::transformDir(toTarget, iworld);
    float r = std::atan2(toTargetLocal[1], toTargetLocal[0]);

    constrainRotation(*fk1, r);
    fk1->angle = r;
}

void IKConstraint::solve2(BoneChainLink* fk1,
                          BoneChainLink* fk2,
                          const Vec2D& worldTargetTranslation) {
    Bone* b1 = fk1->bone;
    Bone* b2 = fk2->bone;
    BoneChainLink* firstChild = &(m_FkChain[fk1->index + 1]);

    const Mat2D& iworld = fk1->parentWorldInverse;

    Vec2D pA, pC, pB;
    b1->worldTranslation(pA);
    firstChild->bone->worldTranslation(pC);
    b2->tipWorldTranslation(pB);
    Vec2D pBT(worldTargetTranslation);

    pA = iworld * pA;
    pC = iworld * pC;
    pB = iworld * pB;
    pBT = iworld * pBT;

    // http://mathworld.wolfram.com/LawofCosines.html
    Vec2D av = pB - pC, bv = pC - pA, cv = pBT - pA;
    float a = av.length(), b = bv.length(), c = cv.length();

    float A = std::acos(std::max(-1.0f, std::min(1.0f, (-a * a + b * b + c * c) / (2.0f * b * c))));
    float C = std::acos(std::max(-1.0f, std::min(1.0f, (a * a + b * b - c * c) / (2.0f * a * b))));

    float r1, r2;
    if (b2->parent() != b1) {
        BoneChainLink& secondChild = m_FkChain[fk1->index + 2];

        const Mat2D& secondChildWorldInverse = secondChild.parentWorldInverse;

        firstChild->bone->worldTranslation(pC);
        b2->tipWorldTranslation(pB);

        Vec2D avLocal = Vec2D::transformDir(pB - pC, secondChildWorldInverse);
        float angleCorrection = -std::atan2(avLocal[1], avLocal[0]);

        if (invertDirection()) {
            r1 = std::atan2(cv[1], cv[0]) - A;
            r2 = -C + M_PI + angleCorrection;
        } else {
            r1 = A + std::atan2(cv[1], cv[0]);
            r2 = C - M_PI + angleCorrection;
        }
    } else if (invertDirection()) {
        r1 = std::atan2(cv[1], cv[0]) - A;
        r2 = -C + M_PI;
    } else {
        r1 = A + std::atan2(cv[1], cv[0]);
        r2 = C - M_PI;
    }

    constrainRotation(*fk1, r1);
    constrainRotation(*firstChild, r2);
    if (firstChild != fk2) {
        Bone* bone = fk2->bone;
        bone->mutableWorldTransform() = getParentWorld(*bone) * bone->transform();
    }

    // Simple storage, need this for interpolation.
    fk1->angle = r1;
    firstChild->angle = r2;
}

void IKConstraint::constrainRotation(BoneChainLink& fk, float rotation) {
    Bone* bone = fk.bone;
    const Mat2D& parentWorld = getParentWorld(*bone);
    Mat2D& transform = bone->mutableTransform();
    TransformComponents& c = fk.transformComponents;

    transform = Mat2D::fromRotation(rotation);

    // Translate
    transform[4] = c.x();
    transform[5] = c.y();
    // Scale
    float scaleX = c.scaleX();
    float scaleY = c.scaleY();
    transform[0] *= scaleX;
    transform[1] *= scaleX;
    transform[2] *= scaleY;
    transform[3] *= scaleY;

    // Skew
    const float skew = c.skew();
    if (skew != 0.0f) {
        transform[2] = transform[0] * skew + transform[2];
        transform[3] = transform[1] * skew + transform[3];
    }

    bone->mutableWorldTransform() = parentWorld * transform;
}

void IKConstraint::constrain(TransformComponent* component) {
    if (m_Target == nullptr) {
        return;
    }

    Vec2D worldTargetTranslation;
    m_Target->worldTranslation(worldTargetTranslation);

    // Decompose the chain.
    for (BoneChainLink& item : m_FkChain) {
        auto bone = item.bone;
        const Mat2D& parentWorld = getParentWorld(*bone);
        item.parentWorldInverse = parentWorld.invertOrIdentity();

        Mat2D& boneTransform = bone->mutableTransform();
        boneTransform = item.parentWorldInverse * bone->worldTransform();
        item.transformComponents = boneTransform.decompose();
    }

    int count = (int)m_FkChain.size();
    switch (count) {
        case 1:
            solve1(&m_FkChain[0], worldTargetTranslation);
            break;
        case 2:
            solve2(&m_FkChain[0], &m_FkChain[1], worldTargetTranslation);
            break;
        default: {
            auto last = count - 1;
            BoneChainLink* tip = &m_FkChain[last];
            for (int i = 0; i < last; i++) {
                BoneChainLink* item = &m_FkChain[i];
                solve2(item, tip, worldTargetTranslation);
                for (int j = item->index + 1, end = m_FkChain.size() - 1; j < end; j++) {
                    BoneChainLink& fk = m_FkChain[j];
                    fk.parentWorldInverse = getParentWorld(*fk.bone).invertOrIdentity();
                }
            }
            break;
        }
    }
    // At the end, mix the FK angle with the IK angle by strength
    if (strength() != 1.0f) {
        for (BoneChainLink& fk : m_FkChain) {
            float fromAngle = std::fmod(fk.transformComponents.rotation(), (float)M_PI * 2);
            float toAngle = std::fmod(fk.angle, (float)M_PI * 2);
            float diff = toAngle - fromAngle;
            if (diff > M_PI) {
                diff -= M_PI * 2;
            } else if (diff < -M_PI) {
                diff += M_PI * 2;
            }
            float angle = fromAngle + diff * strength();
            constrainRotation(fk, angle);
        }
    }
}
