#include "pch.h"

#include "AnimationParameter.h"
#include "Mesh2D.h"
#include "ModelPart.h"

#include <algorithm>
#include <cmath>
#include <sstream>
#include <iomanip>
#include <limits>

namespace Vivid2D {

    // --- AnimationParameter 实现 (与你提供的代码相同) ---
    AnimationParameter::AnimationParameter(std::string id, float min, float max, float defaultValue)
        : m_Id(std::move(id)),
        m_DefaultValue(defaultValue),
        m_MinValue(min),
        m_MaxValue(max) {
        m_Value = defaultValue;
    }

    void AnimationParameter::setValue(float value) {
        float clamped = std::clamp(value, m_MinValue, m_MaxValue);
        if (m_Value != clamped) {
            m_Value = clamped;
            m_Changed = true;
        }
    }

    AnimationParameter AnimationParameter::copy() const {
        AnimationParameter cpy(m_Id, m_MinValue, m_MaxValue, m_DefaultValue);
        cpy.m_Value = m_Value;
        cpy.m_Changed = m_Changed;
        cpy.m_Keyframes = m_Keyframes;
        return cpy;
    }

    bool AnimationParameter::hasChanged() const { return m_Changed; }
    void AnimationParameter::markClean() { m_Changed = false; }
    float AnimationParameter::getValue() const { return m_Value; }
    const std::string& AnimationParameter::getId() const { return m_Id; }
    float AnimationParameter::getMinValue() const { return m_MinValue; }
    float AnimationParameter::getMaxValue() const { return m_MaxValue; }
    float AnimationParameter::getDefaultValue() const { return m_DefaultValue; }
    void AnimationParameter::reset() { setValue(m_DefaultValue); }

    float AnimationParameter::getNormalizedValue() const {
        float range = m_MaxValue - m_MinValue;
        if (range == 0.0f) return 0.0f;
        return (m_Value - m_MinValue) / range;
    }

    void AnimationParameter::setNormalizedValue(float normalized) {
        float newValue = m_MinValue + normalized * (m_MaxValue - m_MinValue);
        setValue(newValue);
    }

    bool AnimationParameter::addKeyframe(float frameValue) {
        float clamped = std::clamp(frameValue, m_MinValue, m_MaxValue);
        return m_Keyframes.insert(clamped).second;
    }

    bool AnimationParameter::removeKeyframe(float frameValue) {
        return m_Keyframes.erase(frameValue) > 0;
    }

    bool AnimationParameter::isKeyframe(float frameValue) const {
        return m_Keyframes.count(frameValue) > 0;
    }

    const std::set<float>& AnimationParameter::getKeyframes() const {
        return m_Keyframes;
    }

    void AnimationParameter::clearKeyframes() {
        m_Keyframes.clear();
    }

    std::optional<float> AnimationParameter::getNearestKeyframe(float value, float snapThreshold) const {
        if (snapThreshold <= 0 || m_Keyframes.empty()) {
            return std::nullopt;
        }
        auto it_next = m_Keyframes.lower_bound(value);
        std::optional<float> prev_key;
        float distToPrev = std::numeric_limits<float>::max();
        if (it_next != m_Keyframes.begin()) {
            auto it_prev = std::prev(it_next);
            prev_key = *it_prev;
            distToPrev = std::abs(*it_prev - value);
        }
        std::optional<float> next_key;
        float distToNext = std::numeric_limits<float>::max();
        if (it_next != m_Keyframes.end()) {
            next_key = *it_next;
            distToNext = std::abs(*it_next - value);
        }
        if (distToPrev < snapThreshold && distToPrev <= distToNext) {
            return prev_key;
        }
        if (distToNext < snapThreshold && distToNext < distToPrev) {
            return next_key;
        }
        return std::nullopt;
    }

    bool AnimationParameter::operator==(const AnimationParameter& other) const {
        return m_Id == other.m_Id &&
            m_DefaultValue == other.m_DefaultValue &&
            m_MinValue == other.m_MinValue &&
            m_MaxValue == other.m_MaxValue &&
            m_Keyframes == other.m_Keyframes;
    }

    std::string AnimationParameter::toString() const {
        std::stringstream ss;
        ss << std::fixed << std::setprecision(3);
        ss << "AnimationParameter[ID=" << m_Id
            << ", Value=" << m_Value
            << (m_Changed ? " (Changed)" : "")
            << ", Range=[" << m_MinValue << ", " << m_MaxValue << "]"
            << ", Default=" << m_DefaultValue
            << ", Keyframes=[";
        for (auto it = m_Keyframes.begin(); it != m_Keyframes.end(); ++it) {
            ss << (it == m_Keyframes.begin() ? "" : ", ") << *it;
        }
        ss << "]]";
        return ss.str();
    }

    // --- 新增：ParametersManagement 和相关实现 ---

    void ParametersManagement::broadcast(ModelPart* modelPart, const AnimationParameter& currentAnimParam, float currentKeyframe, const std::string& paramId, const ParameterValue& value) {
        if (!modelPart) return;

        bool isKeyframe = currentAnimParam.isKeyframe(currentKeyframe);

        // 查找或创建 modelPart 对应的记录
        auto& record = m_records[modelPart];
        record.modelPart = modelPart;

        // 检查是否存在完全匹配的记录 (keyframe, paramId, animParam, and special id for mesh)
        long existingIndex = -1;
        for (size_t i = 0; i < record.keyframes.size(); ++i) {
            bool keyframeMatches = record.keyframes[i] == currentKeyframe;
            bool paramIdMatches = record.paramIds[i] == paramId;
            bool animParamMatches = record.animationParameters[i] == currentAnimParam;
            bool idMatches = true;

            // 对 meshVertices 进行特殊处理
            if (paramIdMatches && paramId == "meshVertices") {
                const auto* currentMap = std::get_if<std::map<std::string, std::any>>(&value);
                const auto* recordMap = std::get_if<std::map<std::string, std::any>>(&record.values[i]);
                if (currentMap && recordMap) {
                    auto currentIdIt = currentMap->find("id");
                    auto recordIdIt = recordMap->find("id");
                    if (currentIdIt != currentMap->end() && recordIdIt != recordMap->end()) {
                        const std::string* currentId = std::any_cast<std::string>(&currentIdIt->second);
                        const std::string* recordId = std::any_cast<std::string>(&recordIdIt->second);
                        idMatches = (currentId && recordId && *currentId == *recordId);
                    }
                    else {
                        idMatches = false; // 如果任一map中没有id，则认为不匹配
                    }
                }
                else {
                    idMatches = false;
                }
            }

            if (keyframeMatches && paramIdMatches && animParamMatches && idMatches) {
                existingIndex = i;
                break;
            }
        }

        if (existingIndex != -1) {
            // 更新现有值
            record.values[existingIndex] = value;
            record.isKeyframes[existingIndex] = isKeyframe; // 状态也可能变化
        }
        else {
            // 添加新记录
            record.animationParameters.push_back(currentAnimParam);
            record.paramIds.push_back(paramId);
            record.values.push_back(value);
            record.keyframes.push_back(currentKeyframe);
            record.isKeyframes.push_back(isKeyframe);
        }
    }

    void ParametersManagement::removeParameterAt(ModelPart* targetModelPart, size_t indexToRemove) {
        auto it = m_records.find(targetModelPart);
        if (it != m_records.end()) {
            ParameterRecord& record = it->second;
            if (indexToRemove < record.paramIds.size()) {
                record.animationParameters.erase(record.animationParameters.begin() + indexToRemove);
                record.paramIds.erase(record.paramIds.begin() + indexToRemove);
                record.values.erase(record.values.begin() + indexToRemove);
                record.keyframes.erase(record.keyframes.begin() + indexToRemove);
                record.isKeyframes.erase(record.isKeyframes.begin() + indexToRemove);
            }
            // 如果记录变空，则从 map 中移除
            if (record.paramIds.empty()) {
                m_records.erase(it);
            }
        }
    }

    void ParametersManagement::removeParameter(ModelPart* modelPart, const std::string& paramId) {
        auto it = m_records.find(modelPart);
        if (it == m_records.end()) return;

        if (paramId == "all") {
            m_records.erase(it);
            return;
        }

        ParameterRecord& record = it->second;
        // 从后往前遍历以安全删除
        for (int i = record.paramIds.size() - 1; i >= 0; --i) {
            if (record.paramIds[i] == paramId) {
                record.animationParameters.erase(record.animationParameters.begin() + i);
                record.paramIds.erase(record.paramIds.begin() + i);
                record.values.erase(record.values.begin() + i);
                record.keyframes.erase(record.keyframes.begin() + i);
                record.isKeyframes.erase(record.isKeyframes.begin() + i);
            }
        }

        if (record.paramIds.empty()) {
            m_records.erase(it);
        }
    }

    std::optional<ParameterRecord> ParametersManagement::getValue(ModelPart* modelPart, const std::string& paramId) const {
        auto it = m_records.find(modelPart);
        if (it == m_records.end()) {
            return std::nullopt;
        }

        const ParameterRecord& sourceRecord = it->second;
        ParameterRecord resultRecord;
        resultRecord.modelPart = modelPart;

        for (size_t i = 0; i < sourceRecord.paramIds.size(); ++i) {
            if (sourceRecord.paramIds[i] == paramId) {
                resultRecord.animationParameters.push_back(sourceRecord.animationParameters[i]);
                resultRecord.paramIds.push_back(sourceRecord.paramIds[i]);
                resultRecord.values.push_back(sourceRecord.values[i]);
                resultRecord.keyframes.push_back(sourceRecord.keyframes[i]);
                resultRecord.isKeyframes.push_back(sourceRecord.isKeyframes[i]);
            }
        }

        if (resultRecord.paramIds.empty()) {
            return std::nullopt;
        }

        return resultRecord;
    }

    const ParameterRecord* ParametersManagement::getModelPartParameters(ModelPart* modelPart) const {
        auto it = m_records.find(modelPart);
        if (it != m_records.end()) {
            return &it->second;
        }
        return nullptr;
    }

    const std::map<ModelPart*, ParameterRecord>& ParametersManagement::getAllRecords() const {
        return m_records;
    }

    // --- toString 实现 ---

    // 辅助函数，用于将 ParameterValue 转换为字符串
    std::string parameterValueToString(const ParameterValue& value) {
        std::stringstream ss;
        std::visit([&ss](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, std::monostate>) {
                ss << "[Null]";
            }
            else if constexpr (std::is_same_v<T, float>) {
                ss << arg;
            }
            else if constexpr (std::is_same_v<T, std::pair<float, float>>) {
                ss << "(" << arg.first << ", " << arg.second << ")";
            }
            else if constexpr (std::is_same_v<T, std::map<std::string, std::any>>) {
                ss << "{";
                for (auto it = arg.begin(); it != arg.end(); ++it) {
                    ss << (it == arg.begin() ? "" : ", ") << it->first << ":";
                    if (it->second.type() == typeid(std::string)) {
                        ss << "\"" << std::any_cast<std::string>(it->second) << "\"";
                    }
                    else {
                        ss << "[... complex data ...]";
                    }
                }
                ss << "}";
            }
            }, value);
        return ss.str();
    }

    std::string ParameterRecord::toString() const {
        std::stringstream ss;
        std::string partName = (modelPart != nullptr) ? modelPart->getName() : "[NULL ModelPart]";
        ss << "ParameterRecord[Part=" << partName << ", Details=[";
        for (size_t i = 0; i < paramIds.size(); ++i) {
            if (i > 0) ss << "; ";
            ss << "{ID=" << paramIds[i]
                << ", V=" << parameterValueToString(values[i])
                << ", KF=" << keyframes[i]
                << ", IsKF=" << (isKeyframes[i] ? "true" : "false")
                << "}";
        }
        ss << "]]";
        return ss.str();
    }

    std::string ParametersManagement::toString() const {
        std::stringstream ss;
        ss << "ParametersManagement State:\n";
        if (m_records.empty()) {
            ss << "  No recorded parameters.\n";
        }
        else {
            int recordIndex = 0;
            for (const auto& pair : m_records) {
                ss << "  --- Record " << recordIndex++ << " ---\n";
                ss << "  " << pair.second.toString() << "\n";
            }
        }
        return ss.str();
    }

} // namespace Vivid2D