#include "rive/bones/skin.hpp"
#include "rive/bones/bone.hpp"
#include "rive/bones/skinnable.hpp"
#include "rive/bones/tendon.hpp"
#include "rive/shapes/vertex.hpp"
#include "rive/shapes/path_vertex.hpp"
#include "rive/constraints/constraint.hpp"
#include <algorithm>

#include <cmath>

using namespace rive;

Skin::~Skin() { delete[] m_BoneTransforms; }

StatusCode Skin::onAddedDirty(CoreContext* context)
{
    StatusCode code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
    m_WorldTransform[0] = xx();
    m_WorldTransform[1] = xy();
    m_WorldTransform[2] = yx();
    m_WorldTransform[3] = yy();
    m_WorldTransform[4] = tx();
    m_WorldTransform[5] = ty();
    m_Skinnable = Skinnable::from(parent());
    if (m_Skinnable == nullptr)
    {
        return StatusCode::MissingObject;
    }

#ifndef WITH_RIVE_EDITOR
    // Runtime-only; editor build registers via editorParentChanged.
    m_Skinnable->skin(this);
#endif

    return StatusCode::Ok;
}

void Skin::update(ComponentDirt value)
{
    int bidx = 6;
    for (auto tendon : m_Tendons)
    {
#ifdef WITH_RIVE_EDITOR
        // Edit-time: a partially-hydrated coop batch can leave a
        // Tendon with a null `m_Bone` (its Bone hasn't been delivered
        // yet, or was deleted). Without this guard `update` reads the
        // null bone's world transform and crashes mid-frame. Emit the
        // identity transform so the skin can still render in its
        // bind pose until the bone reappears.
        if (tendon->bone() == nullptr)
        {
            const auto& inv = tendon->inverseBind();
            m_BoneTransforms[bidx++] = inv[0];
            m_BoneTransforms[bidx++] = inv[1];
            m_BoneTransforms[bidx++] = inv[2];
            m_BoneTransforms[bidx++] = inv[3];
            m_BoneTransforms[bidx++] = inv[4];
            m_BoneTransforms[bidx++] = inv[5];
            continue;
        }
#endif
        auto world = tendon->bone()->worldTransform() * tendon->inverseBind();
        m_BoneTransforms[bidx++] = world[0];
        m_BoneTransforms[bidx++] = world[1];
        m_BoneTransforms[bidx++] = world[2];
        m_BoneTransforms[bidx++] = world[3];
        m_BoneTransforms[bidx++] = world[4];
        m_BoneTransforms[bidx++] = world[5];
    }
}

int Skin::windingSign() const
{
    if (m_BoneTransforms == nullptr)
    {
        return 0;
    }
    bool anyMirrored = false;
    bool anyUpright = false;
    const float* transform = m_BoneTransforms;
    for (auto tendon : m_Tendons)
    {
        transform += 6;
#ifdef WITH_RIVE_EDITOR
        if (tendon->bone() == nullptr)
        {
            continue;
        }
#else
        (void)tendon;
#endif
        float xxyy = transform[0] * transform[3];
        float xyyx = transform[1] * transform[2];
        float determinant = xxyy - xyyx;
        // A collapsed bone carries no orientation, and its determinant is
        // only zero up to the rounding of the two products.
        if (std::abs(determinant) <= 1e-6f * (std::abs(xxyy) + std::abs(xyyx)))
        {
            continue;
        }
        if (determinant < 0)
        {
            anyMirrored = true;
        }
        else
        {
            anyUpright = true;
        }
    }
    return anyMirrored == anyUpright ? 0 : (anyMirrored ? -1 : 1);
}

void Skin::buildDependencies()
{
    // depend on bones from tendons
    for (auto tendon : m_Tendons)
    {
        auto bone = tendon->bone();
#ifdef WITH_RIVE_EDITOR
        // See `Skin::update` — coop can leave an unresolved Tendon
        // with a null bone. `editor_native/finalizeBatch` calls
        // `Tendon::resolveBone` on every tendon before us, so this
        // is only hit for tendons whose bone genuinely isn't in the
        // file yet. Skip; the dependency edge rewires when the bone
        // arrives in a later batch and we re-run finalizeBatch.
        if (bone == nullptr)
        {
            continue;
        }
#endif
        bone->addDependent(this);
        for (auto constraint : bone->peerConstraints())
        {
            constraint->parent()->addDependent(this);
        }
    }

#ifdef WITH_RIVE_EDITOR
    // Editor re-runs buildDependencies after every batch (Pass-B-prep
    // wipes the dependents list, then the typed per-class method
    // rewires it). For Skin that means a second allocation of the
    // bone-transform buffer — `assert` below would catch the runtime-
    // only invariant. Free the prior buffer so the editor case stays
    // leak-free while keeping the runtime guard intact.
    if (m_BoneTransforms != nullptr)
    {
        delete[] m_BoneTransforms;
        m_BoneTransforms = nullptr;
    }
#else
    // Make sure no-one is calling this twice.
    assert(m_BoneTransforms == nullptr);
#endif
    // We can now init the bone buffer.
    auto size = (m_Tendons.size() + 1) * 6;
    m_BoneTransforms = new float[size];
    m_BoneTransforms[0] = 1;
    m_BoneTransforms[1] = 0;
    m_BoneTransforms[2] = 0;
    m_BoneTransforms[3] = 1;
    m_BoneTransforms[4] = 0;
    m_BoneTransforms[5] = 0;
}

void Skin::deform(Span<Vertex*> vertices)
{
    for (auto vertex : vertices)
    {
        vertex->deform(m_WorldTransform, m_BoneTransforms);
    }
}
void Skin::addTendon(Tendon* tendon)
{
    m_Tendons.push_back(tendon);
#ifdef WITH_RIVE_EDITOR
    bindingChangedForEditor();
#endif
}

#ifdef WITH_RIVE_EDITOR
void Skin::bindingChangedForEditor()
{
    if (m_Skinnable != nullptr)
    {
        m_Skinnable->bindingChangedForEditor();
    }
}

void Skin::sortTendonsForEditor()
{
    auto byChildOrder = [](const Tendon* a, const Tendon* b) {
        return a->childOrder().compareTo(b->childOrder()) < 0;
    };
    if (std::is_sorted(m_Tendons.begin(), m_Tendons.end(), byChildOrder))
    {
        return;
    }
    std::sort(m_Tendons.begin(), m_Tendons.end(), byChildOrder);
    bindingChangedForEditor();
    // Weights index m_BoneTransforms by tendon position, so a reorder has to
    // rebuild the buffer and re-deform the skinnable.
    addDirt(ComponentDirt::WorldTransform);
}
#endif

void Skin::onDirty(ComponentDirt dirt)
{
    if (m_Skinnable != nullptr)
    {
        m_Skinnable->markSkinDirty();
    }
}
