#include "rive/animation/cubic_interpolator.hpp"
#include "rive/artboard.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/importers/import_stack.hpp"
#include <cmath>

using namespace rive;

const int NewtonIterations = 4;
const float NewtonMinSlope = 0.001f;
const float SubdivisionPrecision = 0.0000001f;
const int SubdivisionMaxIterations = 10;

// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
static float calcBezier(float aT, float aA1, float aA2) {
    return (((1.0f - 3.0f * aA2 + 3.0f * aA1) * aT + (3.0f * aA2 - 6.0f * aA1)) * aT +
            (3.0f * aA1)) *
           aT;
}

// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
static float getSlope(float aT, float aA1, float aA2) {
    return 3.0f * (1.0f - 3.0f * aA2 + 3.0f * aA1) * aT * aT +
           2.0f * (3.0f * aA2 - 6.0f * aA1) * aT + (3.0f * aA1);
}

StatusCode CubicInterpolator::onAddedDirty(CoreContext* context) {
    for (int i = 0; i < SplineTableSize; ++i) {
        m_Values[i] = calcBezier(i * SampleStepSize, x1(), x2());
    }
    return StatusCode::Ok;
}

float CubicInterpolator::getT(float x) const {
    float intervalStart = 0.0f;
    int currentSample = 1;
    int lastSample = SplineTableSize - 1;

    for (; currentSample != lastSample && m_Values[currentSample] <= x; ++currentSample) {
        intervalStart += SampleStepSize;
    }
    --currentSample;

    // Interpolate to provide an initial guess for t
    float dist =
        (x - m_Values[currentSample]) / (m_Values[currentSample + 1] - m_Values[currentSample]);
    float guessForT = intervalStart + dist * SampleStepSize;

    float _x1 = x1(), _x2 = x2();

    float initialSlope = getSlope(guessForT, _x1, _x2);
    if (initialSlope >= NewtonMinSlope) {
        for (int i = 0; i < NewtonIterations; ++i) {
            float currentSlope = getSlope(guessForT, _x1, _x2);
            if (currentSlope == 0.0f) {
                return guessForT;
            }
            float currentX = calcBezier(guessForT, _x1, _x2) - x;
            guessForT -= currentX / currentSlope;
        }
        return guessForT;
    } else if (initialSlope == 0.0f) {
        return guessForT;
    } else {
        float aB = intervalStart + SampleStepSize;
        float currentX, currentT;
        int i = 0;
        do {
            currentT = intervalStart + (aB - intervalStart) / 2.0f;
            currentX = calcBezier(currentT, _x1, _x2) - x;
            if (currentX > 0.0f) {
                aB = currentT;
            } else {
                intervalStart = currentT;
            }
        } while (std::abs(currentX) > SubdivisionPrecision && ++i < SubdivisionMaxIterations);
        return currentT;
    }
}

float CubicInterpolator::transform(float mix) const { return calcBezier(getT(mix), y1(), y2()); }

StatusCode CubicInterpolator::import(ImportStack& importStack) {
    auto artboardImporter = importStack.latest<ArtboardImporter>(ArtboardBase::typeKey);
    if (artboardImporter == nullptr) {
        return StatusCode::MissingObject;
    }
    artboardImporter->addComponent(this);
    return Super::import(importStack);
}