#include "Animation.h"
#include "Asset/AssetManager.h"
#include "Asset/Asset_Script.h"
#include "Tool/Math.h"
#include "EngineFrame/Actor/Actor.h"
#include "EngineCore/Game.h"

Animation::Animation()
{
}

Animation::Animation(std::string AniPath)
{
    Init(AniPath);
}

Animation::Animation(std::string AniPath, std::function<std::string(std::string, Animation::ReplaceData)> AdditionalOptions, Animation::ReplaceData data)
{
    this->AdditionalOptions = AdditionalOptions;
    this->AdditionalOptionsData = data;
    Init(AniPath);
}

Animation::~Animation()
{
}

void Animation::Init(std::string AniPath)
{
    Actor::Init();

    AniScriptParser::AniInfo Info = AssetManager::GetInstance().StructAniInfo(AniPath);
    this->AniPath = AniPath;
    this->AnimationFlag = Info.Flag;
    this->FrameArr = Info.Frame;

    for (size_t i = 0; i < this->FrameArr.size(); i++)
    {
        AniScriptParser::AniFrame FrameObj = this->FrameArr[i];
        RefPtr<Sprite> SpriteObj = nullptr;
        if (!FrameObj.Img_Path.empty())
        {
            if (AdditionalOptions)
            {
                FrameObj.Img_Path = AdditionalOptions(FrameObj.Img_Path, this->AdditionalOptionsData);
            }
            SpriteObj = new Sprite(FrameObj.Img_Path, FrameObj.Img_Index);
            SpriteObj->SetAnchor(Vec2(0.5f, 0.5f));
            SpriteObj->SetPos(Vec2(FrameObj.Img_Pos.x, FrameObj.Img_Pos.y));
            SpriteObj->SetVisible(false);
        }
        else
        {
            SpriteObj = new Sprite();
            SpriteObj->SetVisible(false);
            SDL_Log("Animation::Init() SpriteObj is nullptr");
        }
        SpriteArr.push_back(SpriteObj);
        AddChild(SpriteObj);
    }

    // 初始化完毕 如果是第一次初始化 而非重新构造 设置大小为第0帧大小否则天空 地板等依靠大小的初始化会有问题
    if (CurrentIndexT == 0)
        SetSize(SpriteArr[0]->GetSize());
    // 记录总帧数
    TotalFrameIndex = FrameArr.size();
    // TODO 染色

    // 判断是否有Als
    if (Asset_Script::GetInstance().GetFileInfo(AniPath + ".als"))
    {
        AniScriptParser::AlsInfo Info = AssetManager::GetInstance().StructAlsInfo(AniPath + ".als");
        if (Info.AniList.size() > 0)
        {
            std::string Dir = AniPath.substr(0, AniPath.find_last_of("/") + 1);
            for (auto &Ani : Info.AniList)
            {
                RefPtr<Animation> AlsAniObj = new Animation(Dir + Ani.second.path);
                AlsAniObj->SetRenderZOrder(Ani.second.layer[1]);
                AddChild(AlsAniObj);
            }
        }
    }
    FlushFrame(0);
}

void Animation::HandleEvents(SDL_Event *e)
{
}

void Animation::Update(float deltaTime)
{
    // 可用性检查
    if (IsUsability && Visible)
    {
        float dt_ms = deltaTime * 1000.0f;
        // 累加当前帧时间
        CurrentIndexT += dt_ms;
        // 插值模式判断
        InterpolationLogic();

        // 循环处理：只要当前时间超过帧延迟，就切换帧（支持一次跳过多帧）
        while (CurrentIndexT >= NextFrameDelay)
        {
            CurrentIndexT -= NextFrameDelay;
            // 如果当前帧小于总帧数就切换
            if (CurrentFrameIndex < (TotalFrameIndex - 1))
            {
                FlushFrame(CurrentFrameIndex + 1);
            }
            // 说明播放完毕了
            else
            {
                // 如果有循环
                if (AnimationFlag.count("LOOP"))
                {
                    FlushFrame(0);
                }
                // 没有循环触发状态机回调
                else
                {
                    // 将不再可用
                    IsUsability = false;
                    if (EndCallback)
                        EndCallback();
                    break;
                }
            }
        }
        Actor::Update(deltaTime);
    }
}

void Animation::Render()
{
    Actor::Render();
}

void Animation::OnAdded(BaseNode *node)
{
    Actor::OnAdded(node);
    FlushFrame(0);
}

void Animation::Clear()
{
}

void Animation::SetVisible(bool visible)
{
    // 设置启用的时候要更新一下当前帧的渲染信息 避免因为延迟造成的坐标闪烁
    if (visible)
    {
        CurrentFrame->CalcRenderInfoLogic();
        CurrentFrame->CalcRenderInfo();
    }
    Actor::SetVisible(visible);
}

void Animation::FlushFrame(int Index)
{
    // 关闭旧帧显示
    if (CurrentFrame)
        CurrentFrame->SetVisible(false);
    // 同步当前帧编号
    CurrentFrameIndex = Index;
    // 当前帧更换为本帧
    CurrentFrame = SpriteArr[CurrentFrameIndex];
    // 开启新帧显示
    CurrentFrame->SetVisible(true);

    // 如果是整体染色 则直接使用染色帧
    // if (DyeAllFlag) CurrentFrame = DyeFrameList[CurrentFrameIndex];

    AniScriptParser::AniFrame FrameInfo = FrameArr[CurrentFrameIndex];
    // 设置下帧延迟
    NextFrameDelay = FrameInfo.Delay;

    std::unordered_map<std::string, AniScriptParser::AniFlag> FlagBuf = FrameInfo.Flag;
    // 关键帧
    if (FlagBuf.count("SET_FLAG"))
    {
        if (ChangeFrameCallback)
            ChangeFrameCallback(std::get<int>(FlagBuf["SET_FLAG"]));
    }
    // 播放音效
    if (FlagBuf.count("PLAY_SOUND"))
    {
        // TODO 还没有做音效的播放
    }
    // 缩放
    if (FlagBuf.count("IMAGE_RATE"))
    {
        Vec2 Rate = std::get<Vec2>(FlagBuf["IMAGE_RATE"]);
        CurrentFrame->SetScale(Vec2{Rate.x, Rate.y});
    }
    // 线性减淡
    if (FlagBuf.count("GRAPHIC_EFFECT_LINEARDODGE"))
    {
        CurrentFrame->SetBlendMode(LINEARDODGE);
    }
    // 旋转
    if (FlagBuf.count("IMAGE_ROTATE"))
    {
        CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f});
        CurrentFrame->SetRotation(std::get<float>(FlagBuf["IMAGE_ROTATE"]));
    }
    // 染色
    //  if (!DyeAllFlag)
    // 插值模式
    if (FlagBuf.count("INTERPOLATION"))
    {
        // 初始化插值数据
        if (InterpolationFlag.size() == 0)
        {
            // 旧插值数据
            InterpolationFlag.push_back(FrameArr[CurrentFrameIndex]);
            // 新插值数据
            InterpolationFlag.push_back(FrameArr[CurrentFrameIndex + 1]);
        }
    }
    else
    {
        if (InterpolationFlag.size() > 0)
        {
            InterpolationFlag.clear();
        }
    }
    // 如果有描边
    if (IsOutline)
    {
    }
    // Ani的大小同步为精灵帧对象的大小
    SetSize(CurrentFrame->GetSize());
}

void Animation::Reset()
{
    IsUsability = true;
    CurrentIndexT = 0;
    FlushFrame(0);
}

AniScriptParser::AniFrame Animation::GetCurrentFrameInfo()
{
    return FrameArr[CurrentFrameIndex];
}

void Animation::SetFrameIndex(int Index)
{
    FlushFrame(Index);
    CurrentIndexT = 0;
}

void Animation::InterpolationLogic()
{
    if (InterpolationFlag.size() == 0)
        return;
    // 插值倍率
    float InterRate = Math::getUniformVelocity(0, 100, CurrentIndexT, NextFrameDelay) / 100.0f;
    AniScriptParser::AniFrame OldData = InterpolationFlag[0];
    AniScriptParser::AniFrame NewData = InterpolationFlag[1];
    // RGBA插值
    {
        std::vector<int> OldRgbaData = {255, 255, 255, 250};
        std::vector<int> NewRgbaData = {255, 255, 255, 250};
        if (OldData.Flag.count("RGBA"))
            OldRgbaData = std::get<std::vector<int>>(OldData.Flag["RGBA"]);
        if (NewData.Flag.count("RGBA"))
            NewRgbaData = std::get<std::vector<int>>(NewData.Flag["RGBA"]);
        std::vector<int> RgbaData = {
            (int)(OldRgbaData[0] + (NewRgbaData[0] - OldRgbaData[0]) * InterRate),
            (int)(OldRgbaData[1] + (NewRgbaData[1] - OldRgbaData[1]) * InterRate),
            (int)(OldRgbaData[2] + (NewRgbaData[2] - OldRgbaData[2]) * InterRate),
            (int)(OldRgbaData[3] + (NewRgbaData[3] - OldRgbaData[3]) * InterRate)};
        // TODO 染色 和 透明度还没弄
    }
    // 坐标
    {
        Vec2 PosData = {
            (OldData.Img_Pos.x + (NewData.Img_Pos.x - OldData.Img_Pos.x) * InterRate),
            (OldData.Img_Pos.y + (NewData.Img_Pos.y - OldData.Img_Pos.y) * InterRate)};
        CurrentFrame->SetPos(PosData);
    }
    // 缩放
    {
        Vec2 OldRateData = {1.0f, 1.0f};
        Vec2 NewRateData = {1.0f, 1.0f};
        if (OldData.Flag.count("IMAGE_RATE"))
        {
            OldRateData = std::get<Vec2>(OldData.Flag["IMAGE_RATE"]);
        }
        if (NewData.Flag.count("IMAGE_RATE"))
        {
            NewRateData = std::get<Vec2>(NewData.Flag["IMAGE_RATE"]);
        }
        Vec2 RateData = {
            OldRateData.x + (NewRateData.x - OldRateData.x) * InterRate,
            OldRateData.y + (NewRateData.y - OldRateData.y) * InterRate};
        CurrentFrame->SetAnchor(Vec2{0.5f, 0.5f});
        CurrentFrame->SetScale(RateData);
    }
    // 旋转
    {
        float OldAngleData = 0.0;
        float NewAngleData = 0.0;
        if (OldData.Flag.count("IMAGE_ROTATE"))
        {
            OldAngleData = std::get<float>(OldData.Flag["IMAGE_ROTATE"]);
        }
        if (NewData.Flag.count("IMAGE_ROTATE"))
        {
            NewAngleData = std::get<float>(NewData.Flag["IMAGE_ROTATE"]);
        }
        CurrentFrame->SetRotation(OldAngleData + (NewAngleData - OldAngleData) * InterRate);
    }
}
