#include "pch.h"
#include "AnimationClip.h"
#include <stdexcept>
#include <cmath>
#include <algorithm>
#include <limits>
#include <set>

namespace Vivid2D::util {

    // ==================== TimeStamp 实现 ====================

    AnimationClip::TimeStamp AnimationClip::getCurrentTimeMillis() {
        return std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now().time_since_epoch()
        ).count();
    }

    // ==================== AnimationEventMarker 实现 ====================

    AnimationEventMarker::AnimationEventMarker(std::string name, float time, Action action)
        : m_name(std::move(name)), m_time(time), m_action(std::move(action)), m_triggered(false) {}

    void AnimationEventMarker::trigger() {
        if (!m_triggered && m_action) {
            m_action();
            m_triggered = true;
        }
    }

    void AnimationEventMarker::reset() {
        m_triggered = false;
    }

    AnimationEventMarker AnimationEventMarker::copy() const {
        return AnimationEventMarker(m_name, m_time, m_action);
    }

    // ==================== AnimationCurve 实现 ====================

    AnimationCurve::AnimationCurve(std::string parameterId, float defaultValue)
        : m_parameterId(std::move(parameterId)), m_defaultValue(defaultValue) {}

    Keyframe* AnimationCurve::addKeyframe(float time, float value) {
        return addKeyframe(time, value, InterpolationType::LINEAR);
    }

    Keyframe* AnimationCurve::addKeyframe(float time, float value, InterpolationType interpolation) {
        // 1. 移除相同时间的关键帧
        removeKeyframe(time);

        // 2. 创建新关键帧
        auto newKeyframe = std::make_unique<Keyframe>(time, value, interpolation);
        Keyframe* rawPtr = newKeyframe.get();

        // 3. 找到插入位置并保持排序
        auto it = std::lower_bound(m_keyframes.begin(), m_keyframes.end(), time, [](const std::unique_ptr<Keyframe>& kf, float t) {
            return kf->getTime() < t;
            });

        m_keyframes.insert(it, std::move(newKeyframe));
        return rawPtr;
    }

    bool AnimationCurve::removeKeyframe(float time) {
        bool removed = false;
        auto it = std::remove_if(m_keyframes.begin(), m_keyframes.end(),
            [time, &removed](const std::unique_ptr<Keyframe>& kf) {
                if (std::abs(kf->getTime() - time) < 0.0001f) {
                    removed = true;
                    return true;
                }
                return false;
            });

        if (removed) {
            m_keyframes.erase(it, m_keyframes.end());
        }
        return removed;
    }

    Keyframe* AnimationCurve::getKeyframe(float time) {
        for (const auto& kf : m_keyframes) {
            if (std::abs(kf->getTime() - time) < 0.0001f) {
                return kf.get();
            }
        }
        return nullptr;
    }

    float AnimationCurve::sample(float time) const {
        if (m_keyframes.empty()) {
            return m_defaultValue;
        }

        const auto& firstKf = m_keyframes.front();
        if (time <= firstKf->getTime()) {
            return firstKf->getValue();
        }

        const auto& lastKf = m_keyframes.back();
        if (time >= lastKf->getTime()) {
            return lastKf->getValue();
        }

        // 找到 kf2
        auto kf2_it = std::lower_bound(m_keyframes.begin(), m_keyframes.end(), time, [](const std::unique_ptr<Keyframe>& kf, float t) {
            return kf->getTime() < t;
            });

        // kf1 是 kf2 的前一个
        const Keyframe& kf2 = **kf2_it;
        const Keyframe& kf1 = **std::prev(kf2_it);

        return interpolate(kf1, kf2, time);
    }

    float AnimationCurve::interpolate(const Keyframe& kf1, const Keyframe& kf2, float time) const {
        float duration = kf2.getTime() - kf1.getTime();
        if (duration < 0.0001f) return kf1.getValue();

        float t = (time - kf1.getTime()) / duration;

        switch (kf1.getInterpolation()) {
        case InterpolationType::LINEAR:
            return lerp(kf1.getValue(), kf2.getValue(), t);
        case InterpolationType::STEP:
            return kf1.getValue();
        case InterpolationType::SMOOTH:
            return smoothLerp(kf1.getValue(), kf2.getValue(), t);
        case InterpolationType::EASE_IN:
            return easeInLerp(kf1.getValue(), kf2.getValue(), t);
        case InterpolationType::EASE_OUT:
            return easeOutLerp(kf1.getValue(), kf2.getValue(), t);
        case InterpolationType::EASE_IN_OUT:
            return easeInOutLerp(kf1.getValue(), kf2.getValue(), t);
        default:
            return kf1.getValue();
        }
    }

    float AnimationCurve::lerp(float a, float b, float t) {
        return a + (b - a) * t;
    }

    float AnimationCurve::smoothLerp(float a, float b, float t) {
        float t2 = t * t;
        float t3 = t2 * t;
        // Hermite Blend Function (0, 0, 1, 0)
        return a * (2 * t3 - 3 * t2 + 1) + b * (-2 * t3 + 3 * t2);
    }

    float AnimationCurve::easeInLerp(float a, float b, float t) {
        return a + (b - a) * (t * t); // Quad In
    }

    float AnimationCurve::easeOutLerp(float a, float b, float t) {
        return a + (b - a) * (1.0f - (1.0f - t) * (1.0f - t)); // Quad Out
    }

    float AnimationCurve::easeInOutLerp(float a, float b, float t) {
        if (t < 0.5f) {
            return a + (b - a) * (2 * t * t); // Quad In
        }
        else {
            // Quad Out from 0.5 to 1.0, adjusted
            return a + (b - a) * (1.0f - (2 * (1.0f - t) * (1.0f - t)) / 2.0f);
        }
    }

    float* AnimationCurve::getValueRange() {
        static float minMax[2];
        if (m_keyframes.empty()) {
            minMax[0] = m_defaultValue;
            minMax[1] = m_defaultValue;
            return minMax;
        }
        float minVal = (std::numeric_limits<float>::max)();
        float maxVal = (std::numeric_limits<float>::min)();
        for (const auto& kf : m_keyframes) {
            minVal = (std::min)(minVal, kf->getValue());
            maxVal = (std::max)(maxVal, kf->getValue());
        }
        minMax[0] = minVal;
        minMax[1] = maxVal;
        return minMax;
    }

    AnimationCurve AnimationCurve::copy() const {
        return AnimationCurve(*this);
    }

    // ==================== AnimationClip 实现 ====================

    AnimationClip::AnimationClip(std::string name)
        : AnimationClip(std::move(name), 1.0f, 60.0f) {}

    AnimationClip::AnimationClip(std::string name, float duration, float fps)
        : m_name(std::move(name)),
        m_uuid(generate_new_uuid()),
        m_duration((duration > 0.0f) ? duration : 0.0f),
        m_framesPerSecond((fps > 1.0f) ? fps : 1.0f),
        m_looping(true),
        m_author("Unknown"),
        m_description(""),
        m_creationTime(getCurrentTimeMillis()),
        m_lastModifiedTime(m_creationTime) {}

    // --- 元数据/时长修改 ---

    void AnimationClip::setDuration(float duration) {
        this->m_duration = (duration > 0.0f) ? duration : 0.0f;
        markModified();
    }

    void AnimationClip::setFramesPerSecond(float framesPerSecond) {
        this->m_framesPerSecond = (framesPerSecond > 1.0f) ? framesPerSecond : 1.0f;
        markModified();
    }

    void AnimationClip::setUserData(std::map<std::string, std::string> userData) {
        m_userData = std::move(userData);
        markModified();
    }

    void AnimationClip::markModified() {
        m_lastModifiedTime = getCurrentTimeMillis();
    }

    void AnimationClip::updateDurationIfNeeded(float time) {
        if (time > m_duration) {
            m_duration = time;
            markModified();
        }
    }

    AnimationCurve::AnimationCurve(const AnimationCurve& other)
        : m_parameterId(other.m_parameterId), m_defaultValue(other.m_defaultValue)
    {
        // 为 keyframes 预留空间以提高效率
        m_keyframes.reserve(other.m_keyframes.size());
        // 遍历源对象的 keyframes，为每一个 keyframe 创建一个深拷贝
        for (const auto& kf_ptr : other.m_keyframes) {
            m_keyframes.push_back(std::make_unique<Keyframe>(*kf_ptr));
        }
    }

    AnimationCurve& AnimationCurve::operator=(const AnimationCurve& other) {
        if (this == &other) {
            return *this;
        }
        m_parameterId = other.m_parameterId;
        m_defaultValue = other.m_defaultValue;
        m_keyframes.clear();
        m_keyframes.reserve(other.m_keyframes.size());
        for (const auto& kf_ptr : other.m_keyframes) {
            m_keyframes.push_back(std::make_unique<Keyframe>(*kf_ptr));
        }
        return *this;
    }

    // --- 曲线管理 ---

    AnimationCurve* AnimationClip::addCurve(const std::string& parameterId) {
        return addCurve(parameterId, 0.0f);
    }

    AnimationCurve* AnimationClip::addCurve(const std::string& parameterId, float defaultValue) {
        auto curve = std::make_unique<AnimationCurve>(parameterId, defaultValue);
        AnimationCurve* rawPtr = curve.get();
        m_curves[parameterId] = std::move(curve);
        m_defaultValues[parameterId] = defaultValue;
        markModified();
        return rawPtr;
    }

    AnimationCurve* AnimationClip::getCurve(const std::string& parameterId) {
        auto it = m_curves.find(parameterId);
        return (it != m_curves.end()) ? it->second.get() : nullptr;
    }

    bool AnimationClip::removeCurve(const std::string& parameterId) {
        bool removed = m_curves.erase(parameterId) > 0;
        if (removed) {
            m_defaultValues.erase(parameterId);
            markModified();
        }
        return removed;
    }

    bool AnimationClip::hasCurve(const std::string& parameterId) const {
        return m_curves.count(parameterId) > 0;
    }

    std::set<std::string> AnimationClip::getCurveParameterIds() const {
        std::set<std::string> ids;
        for (const auto& pair : m_curves) {
            ids.insert(pair.first);
        }
        return ids;
    }


    // --- 关键帧管理 ---

    Keyframe* AnimationClip::addKeyframe(const std::string& parameterId, float time, float value) {
        return addKeyframe(parameterId, time, value, InterpolationType::LINEAR);
    }

    Keyframe* AnimationClip::addKeyframe(const std::string& parameterId, float time, float value, InterpolationType interpolation) {
        AnimationCurve* curve = getOrCreateCurve(parameterId);
        Keyframe* keyframe = curve->addKeyframe(time, value, interpolation);
        updateDurationIfNeeded(time);
        markModified();
        return keyframe;
    }

    bool AnimationClip::removeKeyframe(const std::string& parameterId, float time) {
        AnimationCurve* curve = getCurve(parameterId);
        if (curve != nullptr) {
            bool removed = curve->removeKeyframe(time);
            if (removed) markModified();
            return removed;
        }
        return false;
    }

    Keyframe* AnimationClip::getKeyframe(const std::string& parameterId, float time) {
        AnimationCurve* curve = getCurve(parameterId);
        return curve ? curve->getKeyframe(time) : nullptr;
    }

    std::vector<const Keyframe*> AnimationClip::getKeyframes(const std::string& parameterId) {
        AnimationCurve* curve = getCurve(parameterId);
        if (!curve) return {};

        std::vector<const Keyframe*> kfPtrs;
        for (const auto& kf_uptr : curve->getKeyframes()) {
            kfPtrs.push_back(kf_uptr.get());
        }
        return kfPtrs;
    }

    // --- 采样系统 ---

    std::map<std::string, float> AnimationClip::sample(float time) {
        std::map<std::string, float> result;
        for (const auto& entry : m_curves) {
            result[entry.first] = entry.second->sample(time);
        }
        return result;
    }

    float AnimationClip::sampleParameter(const std::string& parameterId, float time) {
        AnimationCurve* curve = getCurve(parameterId);
        if (curve) {
            return curve->sample(time);
        }
        // 使用 getOrDefault 逻辑
        auto it = m_defaultValues.find(parameterId);
        return (it != m_defaultValues.end()) ? it->second : 0.0f;
    }

    std::map<std::string, float> AnimationClip::sampleLooped(float time) {
        float effectiveTime = time;
        if (m_looping && m_duration > 0.0f) {
            float numLoops = time / m_duration;
            float floorLoops = floor(numLoops);
            effectiveTime = time - floorLoops * m_duration;
            if (effectiveTime < 0.0f) {
                effectiveTime += m_duration;
            }

        }
        else {
            effectiveTime = (time < m_duration) ? time : m_duration;
        }
        effectiveTime = (effectiveTime > m_duration) ? m_duration : effectiveTime;
        return sample(effectiveTime);
    }

    // --- 事件标记管理 ---

    AnimationEventMarker* AnimationClip::addEventMarker(const std::string& name, float time) {
        return addEventMarker(name, time, nullptr);
    }

    AnimationEventMarker* AnimationClip::addEventMarker(const std::string& name, float time, AnimationEventMarker::Action action) {
        auto marker = std::make_unique<AnimationEventMarker>(name, time, std::move(action));
        AnimationEventMarker* rawPtr = marker.get();

        // 按时间排序插入
        auto it = std::lower_bound(m_eventMarkers.begin(), m_eventMarkers.end(), time, [](const std::unique_ptr<AnimationEventMarker>& m, float t) {
            return m->getTime() < t;
            });

        m_eventMarkers.insert(it, std::move(marker));

        updateDurationIfNeeded(time);
        markModified();
        return rawPtr;
    }

    bool AnimationClip::removeEventMarker(const std::string& name) {
        bool removed = false;
        auto it = std::remove_if(m_eventMarkers.begin(), m_eventMarkers.end(),
            [name, &removed](const std::unique_ptr<AnimationEventMarker>& m) {
                if (m->getName() == name) {
                    removed = true;
                    return true;
                }
                return false;
            });

        if (removed) {
            m_eventMarkers.erase(it, m_eventMarkers.end());
            markModified();
        }
        return removed;
    }

    std::vector<AnimationEventMarker*> AnimationClip::getEventMarkersInRange(float startTime, float endTime) {
        std::vector<AnimationEventMarker*> result;
        for (const auto& marker : m_eventMarkers) {
            if (marker->getTime() >= startTime && marker->getTime() <= endTime) {
                result.push_back(marker.get());
            }
        }
        return result;
    }

    void AnimationClip::triggerEventMarkers(float time, float tolerance) {
        for (const auto& marker : m_eventMarkers) {
            if (std::abs(marker->getTime() - time) <= tolerance) {
                marker->trigger();
            }
        }
    }

    void AnimationClip::resetEventMarkers() {
        for (const auto& marker : m_eventMarkers) {
            marker->reset();
        }
    }

    // --- 工具方法 ---

    AnimationCurve* AnimationClip::getOrCreateCurve(const std::string& parameterId) {
        // C++ 17 std::map::try_emplace 更好，这里用 computeIfAbsent 的等效逻辑
        auto it = m_curves.find(parameterId);
        if (it == m_curves.end()) {
            float defaultValue = 0.0f;
            auto defaultIt = m_defaultValues.find(parameterId);
            if (defaultIt != m_defaultValues.end()) {
                defaultValue = defaultIt->second;
            }
            return addCurve(parameterId, defaultValue);
        }
        return it->second.get();
    }

    void AnimationClip::merge(const AnimationClip& other) { // other 是引用
        if (this == &other) return;
        for (const auto& entry : other.m_curves) {
            const std::string& paramId = entry.first;
            const AnimationCurve* otherCurve = entry.second.get();
            if (this->hasCurve(paramId)) {
                AnimationCurve* thisCurve = this->getCurve(paramId);
                for (const auto& keyframePtr : otherCurve->getKeyframes()) {
                    thisCurve->addKeyframe(keyframePtr->getTime(), keyframePtr->getValue(),
                        keyframePtr->getInterpolation());
                }
            }
            else {
                this->m_curves[paramId] = std::make_unique<AnimationCurve>(otherCurve->copy());
                this->m_defaultValues[paramId] = otherCurve->getDefaultValue();
            }
        }
        for (const auto& markerPtr : other.m_eventMarkers) {
            this->addEventMarker(markerPtr->getName() + "_merged", markerPtr->getTime(),
                markerPtr->getAction());
        }
        this->m_duration = (this->m_duration > other.m_duration) ? this->m_duration : other.m_duration;
        markModified();
    }

    AnimationClip AnimationClip::copy() const {
        AnimationClip copy(m_name + "_copy", m_duration, m_framesPerSecond);
        copy.m_looping = this->m_looping;
        copy.m_author = this->m_author;
        copy.m_description = this->m_description;
        copy.m_creationTime = this->m_creationTime; // 保持创建时间

        // 深拷贝曲线
        for (const auto& entry : this->m_curves) {
            copy.m_curves[entry.first] = std::make_unique<AnimationCurve>(entry.second->copy());
        }

        // 拷贝默认值
        copy.m_defaultValues = this->m_defaultValues;

        // 深拷贝事件标记
        for (const auto& markerPtr : this->m_eventMarkers) {
            copy.m_eventMarkers.push_back(std::make_unique<AnimationEventMarker>(markerPtr->copy()));
        }

        // 拷贝用户数据
        copy.m_userData = this->m_userData;

        return copy;
    }

    int AnimationClip::getFrameCount() const {
        return static_cast<int>(std::ceil(m_duration * m_framesPerSecond));
    }

    int AnimationClip::timeToFrame(float time) const {
        return static_cast<int>(time * m_framesPerSecond);
    }

    float AnimationClip::frameToTime(int frame) const {
        return static_cast<float>(frame) / m_framesPerSecond;
    }

    bool AnimationClip::isTimeInRange(float time) const {
        return time >= 0.0f && time <= m_duration;
    }

    std::map<std::string, std::vector<float>> AnimationClip::getValueBounds() {
        std::map<std::string, std::vector<float>> bounds;

        for (const auto& entry : m_curves) {
            float* minMax = entry.second->getValueRange();
            bounds[entry.first] = { minMax[0], minMax[1] };
        }

        return bounds;
    }

    // --- Getter 封装 ---

    const std::map<std::string, std::unique_ptr<AnimationCurve>>& AnimationClip::getCurves() const {
        return m_curves;
    }

    const std::vector<std::unique_ptr<AnimationEventMarker>>& AnimationClip::getEventMarkers() const {
        return m_eventMarkers;
    }

} // namespace Vivid2D::util