#pragma once
#include "squirrel/SquirrelEx.h"
#include "Actor/Object/BaseObject.h"

static BaseObject *GetBaseObject(HSQUIRRELVM v)
{
    SQUserPointer ptr;
    sq_getuserpointer(v, 2, &ptr);
    BaseObject *obj = (BaseObject *)ptr;
    return obj;
}

static SQInteger SQR_GetPosition(HSQUIRRELVM v)
{
    SQUserPointer ptr;
    sq_getuserpointer(v, 2, &ptr);
    BaseObject *obj = (BaseObject *)ptr;
    VecPos3 Pos = obj->GetPosition();

    sq_newtable(v);
    sq_pushstring(v, _SC("x"), -1);
    sq_pushfloat(v, Pos.x);
    sq_newslot(v, 3, SQFalse);
    sq_pushstring(v, _SC("y"), -1);
    sq_pushfloat(v, Pos.y);
    sq_newslot(v, 3, SQFalse);
    sq_pushstring(v, _SC("z"), -1);
    sq_pushfloat(v, Pos.z);
    sq_newslot(v, 3, SQFalse);

    return 1;
}

static SQInteger SQR_SetPosition(HSQUIRRELVM v)
{
    SQUserPointer ptr;
    sq_getuserpointer(v, 2, &ptr);
    BaseObject *obj = (BaseObject *)ptr;
    SQFloat PosX, PosY, PosZ;
    sq_getfloat(v, 3, &PosX);
    sq_getfloat(v, 4, &PosY);
    sq_getfloat(v, 5, &PosZ);
    obj->SetPosition(VecPos3(PosX, PosY, PosZ));
    return 0;
}

static SQInteger SQR_GetDirection(HSQUIRRELVM v)
{
    BaseObject *obj = GetBaseObject(v);
    sq_pushinteger(v, obj->GetDirection());
    return 1;
}

static SQInteger SQR_SetDirection(HSQUIRRELVM v)
{
    BaseObject *obj = GetBaseObject(v);
    SQInteger Dir;
    sq_getinteger(v, 3, &Dir);
    obj->SetDirection(Dir);
    return 0;
}

static SQInteger SQR_GetVars(HSQUIRRELVM v)
{
    SQUserPointer ptr;
    sq_getuserpointer(v, 2, &ptr);
    BaseObject *obj = (BaseObject *)ptr;
    const SQChar *KeyBuf;
    const SQChar *TypeBuf;
    sq_getstring(v, 3, &KeyBuf);
    sq_getstring(v, 4, &TypeBuf);
    std::string Key(KeyBuf);
    std::string Type(TypeBuf);

    if (Type == "int")
    {
        std::vector<int> ArrBuf = obj->GetObjectVars().GetArray<int>(Key);
        sq_newarray(v, 0);
        for (int i = 0; i < ArrBuf.size(); i++)
        {
            sq_pushinteger(v, ArrBuf[i]);
            sq_arrayappend(v, -2);
        }
    }
    else if (Type == "float")
    {
        std::vector<float> ArrBuf = obj->GetObjectVars().GetArray<float>(Key);
        sq_newarray(v, 0);
        for (int i = 0; i < ArrBuf.size(); i++)
        {
            sq_pushfloat(v, ArrBuf[i]);
            sq_arrayappend(v, -2);
        }
    }
    else if (Type == "string")
    {
        std::vector<std::string> ArrBuf = obj->GetObjectVars().GetArray<std::string>(Key);
        sq_newarray(v, 0);
        for (int i = 0; i < ArrBuf.size(); i++)
        {
            sq_pushstring(v, ArrBuf[i].c_str(), -1);
            sq_arrayappend(v, -2);
        }
    }

    return 1;
}

static SQInteger SQR_SetVars(HSQUIRRELVM v)
{
    SQUserPointer ptr;
    sq_getuserpointer(v, 2, &ptr);
    BaseObject *obj = (BaseObject *)ptr;
    const SQChar *KeyBuf;
    const SQChar *TypeBuf;
    sq_getstring(v, 3, &KeyBuf);
    sq_getstring(v, 4, &TypeBuf);
    std::string Key(KeyBuf);
    std::string Type(TypeBuf);

    if (Type == "int")
    {
        std::vector<int> ArrBuf;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 5)))
        {
            SQInteger value;
            sq_getinteger(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            ArrBuf.push_back(value);
            sq_pop(v, 2);
        }
        sq_pop(v, 1);
        obj->GetObjectVars().AddAll(Key, ArrBuf);
    }
    else if (Type == "float")
    {
        std::vector<float> ArrBuf;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 5)))
        {
            SQFloat value;
            sq_getfloat(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            ArrBuf.push_back(value);
            sq_pop(v, 2);
        }
        sq_pop(v, 1);
        obj->GetObjectVars().SetArray(Key, ArrBuf);
    }
    else if (Type == "string")
    {
        std::vector<std::string> ArrBuf;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 5)))
        {
            const SQChar *value;
            sq_getstring(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            ArrBuf.push_back(value);
            sq_pop(v, 2);
        }
        sq_pop(v, 1);
        obj->GetObjectVars().AddAll(Key, ArrBuf);
    }
    return 0;
}

static void RegisterBaseObjectNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
{
    sq_pushroottable(v);
    sq_pushstring(v, funcName, -1);
    sq_newclosure(v, funcAddr, 0);
    sq_newslot(v, -3, false);
    sq_poptop(v);
}

static void RegisterBaseObject()
{
    SDL_Log("初始化 基础对象-松鼠脚本!");
    HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
    // 坐标
    RegisterBaseObjectNutApi(_SC("sq_GetPosition"), SQR_GetPosition, v);
    RegisterBaseObjectNutApi(_SC("sq_SetPosition"), SQR_SetPosition, v);
    // 朝向
    RegisterBaseObjectNutApi(_SC("sq_GetDirection"), SQR_GetDirection, v);
    RegisterBaseObjectNutApi(_SC("sq_SetDirection"), SQR_SetDirection, v);
    // 数据储存器
    RegisterBaseObjectNutApi(_SC("sq_GetVars"), SQR_GetVars, v);
    RegisterBaseObjectNutApi(_SC("sq_SetVars"), SQR_SetVars, v);
}
