#include "squirrel/SquirrelEx.h"
#include <dirent.h>
#include <string>
#include <fstream>
#include "SquirrelEx.h"
#include "Asset/Asset_Script.h"

SquirrelEx::SquirrelEx()
{
}
SquirrelEx::~SquirrelEx()
{
}
void SquirrelEx::printfunc(HSQUIRRELVM v, const SQChar *s, ...)
{
    va_list vl;
    va_start(vl, s);
    int len = vsnprintf(NULL, 0, (const char *)s, vl);
    if (len <= 0)
    {
        va_end(vl);
        return;
    }
    char *buf = (char *)malloc(len + 1);
    if (!buf)
    {
        va_end(vl);
        return;
    }
    va_end(vl);
    va_start(vl, s);
    vsnprintf(buf, len + 1, (const char *)s, vl);
    va_end(vl);
    SDL_Log("%s", buf);
    va_end(vl);
}

void SquirrelEx::errorfunc(HSQUIRRELVM v, const SQChar *s, ...)
{
    va_list vl;
    va_start(vl, s);
    int len = vsnprintf(NULL, 0, (const char *)s, vl);
    if (len <= 0)
    {
        va_end(vl);
        return;
    }
    char *buf = (char *)malloc(len + 1);
    if (!buf)
    {
        va_end(vl);
        return;
    }
    va_end(vl);
    va_start(vl, s);
    vsnprintf(buf, len + 1, (const char *)s, vl);
    va_end(vl);
    SDL_LogError(0, "%s", buf);
    va_end(vl);
}

bool SquirrelEx::Compilebuffer(std::string Path, std::string Code)
{
    if (v == nullptr)
    {
        SDL_Log("松鼠虚拟机未初始化!");
        return false;
    }
    if (sq_compilebuffer(v, Code.c_str(), Code.length(), Path.c_str(), SQTrue) >= 0)
    {
        sq_pushroottable(v);
        sq_call(v, 1, SQFalse, SQTrue);
        sq_pop(v, 1);
        return true;
    }
    return false;
}

void SquirrelEx::Init()
{
    // 初始化虚拟机
    if (v == nullptr)
        v = sq_open(1024); // 栈大小1024
    sqstd_seterrorhandlers(v);
    sq_pushroottable(v);
    sqstd_register_bloblib(v);
    sqstd_register_iolib(v);
    sqstd_register_systemlib(v);
    sqstd_register_mathlib(v);
    sqstd_register_stringlib(v);

    sq_setprintfunc(v, printfunc, errorfunc);

#ifdef __SWITCH__
#else
    // 获取工作目录 （switch 不允许)
    WorkPath = SDL_GetBasePath();
    FILE *file1 = fopen("DevMode.ini", "rb");
    if (file1)
    {
        sq_enabledebuginfo(v, true);

        dbg = sqdbg_attach_debugger(v);
        sqdbg_listen_socket(dbg, 2222);
        fclose(file1);
    }
#endif

    // 加载脚本
    LoadLocalScript();
}

void SquirrelEx::RequestNetScript(std::string Ip, std::string Port)
{
    // char *response = NULL;
    // size_t response_size = 0;
    // std::string url = "http://" + Ip + ":" + Port + "/get/getadvertisement?key=Files"; // 确保协议正确
    // int result = http_get(url.c_str(), &response, &response_size);
    // if (result == 0 && response != NULL && response_size > 0)
    // {
    //     std::string response_str(response, response_size);
    //     free(response); // 释放内存
    //     nlohmann::json ex1 = nlohmann::json::parse(response_str);
    //     for (const auto &[key, value] : ex1.items())
    //     {
    //         std::string key_str = key;
    //         std::string value_str = value;
    //         bool Flag = Compilebuffer(key_str, value_str);
    //         if (!Flag)
    //         {
    //             SDL_Log("Squirrel Compilebuffer Error! FileName: %s", key_str.c_str());
    //         }
    //     }
    // }
    // else
    // {
    //     if (response)
    //         free(response);
    // }
}

void SquirrelEx::LoadLocalScript()
{

    std::vector<std::string> lines;
    std::ifstream file("sqr/SquirrelFileConfig.cfg");
    if (file.is_open())
    {
        std::string line;
        while (std::getline(file, line))
        {
            lines.push_back(line);
        }
        file.close();
    }
    else
    {
        SDL_LogError(0, "配置文件未找到,请检查项目目录 sqr/SquirrelFileConfig.cfg 文件是否存在");
    }

    for (const auto &line : lines)
    {
        std::string clean_line = line;
        // 移除换行符和回车符
        clean_line.erase(std::remove(clean_line.begin(), clean_line.end(), '\n'), clean_line.end());
        clean_line.erase(std::remove(clean_line.begin(), clean_line.end(), '\r'), clean_line.end());
        if (line.find(".nut") == std::string::npos)
            continue;

        std::string RegistPath = "sqr/" + clean_line;

#ifndef __SWITCH__
        std::replace(RegistPath.begin(), RegistPath.end(), '/', '\\');
        RegistPath = WorkPath + RegistPath;

        _scriptmap[RegistPath] = Tool_get_file_size(RegistPath);
#endif

        if (!SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(RegistPath.c_str()), SQFalse, SQTrue)))
        {
            SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
        }
        {
            // std::ifstream F;
            // F.open((RegistPath).c_str(), std::ios::in | std::ios::binary);
            // if (F.is_open())
            // {
            //     std::stringstream ContentStringStream;
            //     ContentStringStream << F.rdbuf();
            //     std::string ContentString(ContentStringStream.str());

            //     std::string RealContentString = ContentString;
            //     if (RealContentString.length() > 0)
            //     {
            //         if (SQ_SUCCEEDED(sq_compilebuffer(v, (SQChar *)(RealContentString.c_str()), RealContentString.length(), (SQChar *)(RegistPath.c_str()), true)))
            //         {
            //             sq_pushroottable(v);
            //             sq_call(v, 1, 1, 1);
            //             sq_pop(v, 1);
            //         }
            //     }
            // }
            // else
            // {
            //     SDL_LogError(0, "脚本文件未找到,请检查项目目录 %s 文件是否存在", RegistPath.c_str());
            // }
            // F.close();
        }
    }
}

void SquirrelEx::Run()
{
    // 载入main函数
    SQInteger top = sq_gettop(v); // saves the stack size before the call
    sq_pushroottable(v);          // pushes the global table
    sq_pushstring(v, _SC("main"), -1);
    if (SQ_SUCCEEDED(sq_get(v, -2)))
    {                                   // gets the field 'foo' from the global table
        sq_pushroottable(v);            // push the 'this' (in this case is the global table)
        sq_call(v, 1, SQFalse, SQTrue); // calls the function
    }
    sq_settop(v, top); // restores the original stack size
}

void SquirrelEx::Update(float Dt)
{
#ifdef __SWITCH__
#else
    sqdbg_frame(dbg);

    // 热重载
    if (HotReload)
    {
        for (auto &script : _scriptmap)
        {
            std::string path = script.first;
            int value = script.second;
            int newvalue = Tool_get_file_size(path);
            if (value != newvalue)
            {
                if (SQ_SUCCEEDED(sqstd_dofile(v, (SQChar *)(path.c_str()), SQFalse, SQTrue)))
                {
                    SDL_Log("脚本文件热重载成功 %s", path.c_str());
                    _scriptmap[path] = newvalue;
                }
                else
                {
                    SDL_Log("脚本文件热重载失败 %s", path.c_str());
                }
            }
        }
    }
#endif
}

void SquirrelEx::Clean()
{
    sq_close(v);
    v = nullptr;
}

HSQUIRRELVM SquirrelEx::GetSquirrelVM()
{
    return v;
}
