#pragma once
#include "Sqr_CommonFunc.hpp"
#include "EngineFrame/Component/Sprite.h"
#include "EngineFrame/Component/Canvas.h"
#include "EngineFrame/Component/Text.h"

static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size))
{
    Actor *Abli = (Actor *)p;
    Abli->Release();
    return 0;
}
static SQInteger SQR_RegisterDestruction(HSQUIRRELVM v)
{
    // 析构函数测试
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    sq_setinstanceup(v, 3, P);
    sq_setreleasehook(v, 3, _file_releasehook);
    return 0;
}

static SQInteger SQR_CreateActor(HSQUIRRELVM v)
{
    RefPtr<Actor> act = new Actor();
    act->Retain();
    sq_pushuserpointer(v, act.Get());
    return 1;
}

static SQInteger SQR_SetName(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    const SQChar *name;
    sq_getstring(v, 3, &name);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetName(name);

    return 0;
}

static SQInteger SQR_GetName(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    sq_pushstring(v, Aobj->GetName().c_str(), -1);
    return 1;
}

static SQInteger SQR_AddChild(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQUserPointer B_obj;
    sq_getuserpointer(v, 3, &B_obj);
    Actor *Aobj = (Actor *)A_obj;
    Actor *Bobj = (Actor *)B_obj;
    Aobj->AddChild(Bobj);
    return 0;
}

static SQInteger SQR_RemoveChild(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQUserPointer B_obj;
    sq_getuserpointer(v, 3, &B_obj);
    Actor *Aobj = (Actor *)A_obj;
    Actor *Bobj = (Actor *)B_obj;
    Aobj->RemoveChild(Bobj);
    return 0;
}

static SQInteger SQR_GetZOrder(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    sq_pushinteger(v, Aobj->GetRenderZOrder());
    return 1;
}

static SQInteger SQR_SetZOrder(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQInteger Value;
    sq_getinteger(v, 3, &Value);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetRenderZOrder(Value);
    return 0;
}

static SQInteger SQR_GetPos(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    Vec2 Pos = Aobj->GetPos();

    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);
    return 1;
}

static SQInteger SQR_SetPos(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);

    if (sq_gettop(v) == 3)
    {
        Vec2 Pos;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 3)))
        {
            SQFloat value;
            sq_getfloat(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            if (strcmp(key, _SC("x")) == 0)
            {
                Pos.x = value;
            }
            else if (strcmp(key, _SC("y")) == 0)
            {
                Pos.y = value;
            }
            sq_pop(v, 2);
        }
        sq_pop(v, 1);

        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetPos(Pos);
    }
    else if (sq_gettop(v) == 4)
    {
        SQFloat X, Y;
        sq_getfloat(v, 3, &X);
        sq_getfloat(v, 4, &Y);
        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetPos(Vec2(X, Y));
    }
    return 0;
}

static SQInteger SQR_GetWorldPos(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    Vec2 Pos = Aobj->GetWorldPos();

    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);
    return 1;
}

static SQInteger SQR_GetAlpha(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;

    sq_pushfloat(v, Aobj->GetAlpha());
    return 1;
}
static SQInteger SQR_SetAlpha(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQFloat Value;
    sq_getfloat(v, 3, &Value);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetAlpha(Value);
    return 0;
}

static SQInteger SQR_GetScale(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    Vec2 Pos = Aobj->GetScale();
    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);
    return 1;
}

static SQInteger SQR_SetScale(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);

    if (sq_gettop(v) == 3)
    {
        Vec2 Pos;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 3)))
        {
            SQFloat value;
            sq_getfloat(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            if (strcmp(key, _SC("x")) == 0)
            {
                Pos.x = value;
            }
            else if (strcmp(key, _SC("y")) == 0)
            {
                Pos.y = value;
            }
            sq_pop(v, 2);
        }
        sq_pop(v, 1);

        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetScale(Pos);
    }
    else if (sq_gettop(v) == 4)
    {
        SQFloat X, Y;
        sq_getfloat(v, 3, &X);
        sq_getfloat(v, 4, &Y);
        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetScale(Vec2(X, Y));
    }
    return 0;
}

static SQInteger SQR_GetRotation(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;

    sq_pushfloat(v, Aobj->GetRotation());
    return 1;
}

static SQInteger SQR_SetRotation(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQFloat Value;
    sq_getfloat(v, 3, &Value);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetRotation(Value);
    return 0;
}

static SQInteger SQR_GetSize(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    VecSize Pos = Aobj->GetSize();

    sq_newtable(v);
    sq_pushstring(v, _SC("w"), -1);
    sq_pushfloat(v, Pos.width);
    sq_newslot(v, 3, SQFalse);
    sq_pushstring(v, _SC("h"), -1);
    sq_pushfloat(v, Pos.height);
    sq_newslot(v, 3, SQFalse);
    return 1;
}

static SQInteger SQR_SetSize(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);

    if (sq_gettop(v) == 3)
    {
        VecSize Size;
        sq_pushnull(v); // null iterator
        while (SQ_SUCCEEDED(sq_next(v, 3)))
        {
            SQFloat value;
            sq_getfloat(v, -1, &value);
            const SQChar *key;
            sq_getstring(v, -2, &key);

            if (strcmp(key, _SC("w")) == 0)
            {
                Size.width = value;
            }
            else if (strcmp(key, _SC("h")) == 0)
            {
                Size.height = value;
            }
            sq_pop(v, 2);
        }
        sq_pop(v, 1);

        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetSize(Size);
    }
    else if (sq_gettop(v) == 4)
    {
        SQFloat X, Y;
        sq_getfloat(v, 3, &X);
        sq_getfloat(v, 4, &Y);
        Actor *Aobj = (Actor *)A_obj;
        Aobj->SetSize(VecSize(X, Y));
    }
    return 0;
}

static SQInteger SQR_SetVisible(HSQUIRRELVM v){
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQBool Value;
    sq_getbool(v, 3, &Value);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetVisible(Value);
    return 0;
}

static SQInteger SQR_GetVisible(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    Actor *Aobj = (Actor *)A_obj;
    sq_pushbool(v, Aobj->GetVisible());
    return 1;
}

static SQInteger SQR_SetBlendMode(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    sq_getuserpointer(v, 2, &A_obj);
    SQInteger Value;
    sq_getinteger(v, 3, &Value);
    Actor *Aobj = (Actor *)A_obj;
    Aobj->SetBlendMode((LE_BlEND_MODE)Value);
    return 0;
}

static SQInteger SQR_CreateSprite(HSQUIRRELVM v)
{
    const SQChar *ImgPath;
    SQInteger Idx;
    sq_getstring(v, 2, &ImgPath);
    sq_getinteger(v, 3, &Idx);
    RefPtr<Sprite> act = new Sprite(ImgPath, Idx);
    act->Retain();
    sq_pushuserpointer(v, act.Get());
    return 1;
}

static SQInteger SQR_CreateCanvas(HSQUIRRELVM v)
{
    SQInteger Width, Height;
    sq_getinteger(v, 2, &Width);
    sq_getinteger(v, 3, &Height);
    RefPtr<Canvas> act = new Canvas(VecSize(Width, Height));
    act->Retain();
    sq_pushuserpointer(v, act.Get());
    return 1;
}

static SQInteger SQR_Canvas_DrawImg(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    const SQChar *ImgPath;
    SQInteger Idx;
    Vec2 Pos;
    sq_getuserpointer(v, 2, &A_obj);
    sq_getstring(v, 3, &ImgPath);
    sq_getinteger(v, 4, &Idx);
    sq_GetVec2(v, 5, &Pos);
    Canvas *Aobj = (Canvas *)A_obj;
    Aobj->DrawImg(ImgPath, Idx, Pos);
    return 0;
}

static SQInteger SQR_Canvas_DrawImgRect(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    const SQChar *ImgPath;
    SQInteger Idx;
    SDL_FRect Rect;
    sq_getuserpointer(v, 2, &A_obj);
    sq_getstring(v, 3, &ImgPath);
    sq_getinteger(v, 4, &Idx);
    sq_GetFRect(v, 5, &Rect);
    Canvas *Aobj = (Canvas *)A_obj;
    Aobj->DrawImg(ImgPath, Idx, Rect);
    return 0;
}

static SQInteger SQR_CreateText(HSQUIRRELVM v)
{
    const SQChar *Str;
    SQInteger FontIndex, FontColor;
    SDL_Color color;
    sq_getstring(v, 2, &Str);
    sq_getinteger(v, 3, &FontIndex);
    sq_getinteger(v, 4, &FontColor);
    color.a = (FontColor >> 24) & 0xFF;
    color.r = (FontColor >> 16) & 0xFF;
    color.g = (FontColor >> 8) & 0xFF;
    color.b = FontColor & 0xFF;
    RefPtr<Text> act = new Text();
    act->Init(Str, Global_Game::GetInstance().Fonts[FontIndex], color);
    act->Retain();
    sq_pushuserpointer(v, act.Get());
    return 1;
}

static SQInteger SQR_Text_SetText(HSQUIRRELVM v)
{
    SQUserPointer A_obj;
    const SQChar *Str;
    sq_getuserpointer(v, 2, &A_obj);
    sq_getstring(v, 3, &Str);
    Text *Aobj = (Text *)A_obj;
    Aobj->SetText(Str);
    return 0;
}

static void RegisterUINutApi(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 RegisterUI()
{
    SDL_Log("初始化 UI函数-松鼠脚本!");
    HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();

    // 析构函数
    RegisterUINutApi(_SC("sq_RegisterDestruction"), SQR_RegisterDestruction, v);

    RegisterUINutApi(_SC("sq_CreateActor"), SQR_CreateActor, v);
    RegisterUINutApi(_SC("sq_SetName"), SQR_SetName, v);
    RegisterUINutApi(_SC("sq_GetName"), SQR_GetName, v);
    RegisterUINutApi(_SC("sq_AddChild"), SQR_AddChild, v);
    RegisterUINutApi(_SC("sq_RemoveChild"), SQR_RemoveChild, v);
    RegisterUINutApi(_SC("sq_GetZOrder"), SQR_GetZOrder, v);
    RegisterUINutApi(_SC("sq_SetZOrder"), SQR_SetZOrder, v);
    RegisterUINutApi(_SC("sq_GetPos"), SQR_GetPos, v);
    RegisterUINutApi(_SC("sq_SetPos"), SQR_SetPos, v);
    RegisterUINutApi(_SC("sq_GetWorldPos"), SQR_GetWorldPos, v);
    RegisterUINutApi(_SC("sq_GetAlpha"), SQR_GetAlpha, v);
    RegisterUINutApi(_SC("sq_SetAlpha"), SQR_SetAlpha, v);
    RegisterUINutApi(_SC("sq_GetScale"), SQR_GetScale, v);
    RegisterUINutApi(_SC("sq_SetScale"), SQR_SetScale, v);
    RegisterUINutApi(_SC("sq_GetRotation"), SQR_GetRotation, v);
    RegisterUINutApi(_SC("sq_SetRotation"), SQR_SetRotation, v);
    RegisterUINutApi(_SC("sq_GetSize"), SQR_GetSize, v);
    RegisterUINutApi(_SC("sq_SetSize"), SQR_SetSize, v);
    RegisterUINutApi(_SC("sq_SetVisible"), SQR_SetVisible, v);
    RegisterUINutApi(_SC("sq_GetVisible"), SQR_GetVisible, v);
    RegisterUINutApi(_SC("sq_SetBlendMode"), SQR_SetBlendMode, v);

    RegisterUINutApi(_SC("sq_CreateSprite"), SQR_CreateSprite, v);

    RegisterUINutApi(_SC("sq_CreateCanvas"), SQR_CreateCanvas, v);
    RegisterUINutApi(_SC("sq_Canvas_DrawImg"), SQR_Canvas_DrawImg, v);
    RegisterUINutApi(_SC("sq_Canvas_DrawImgRect"), SQR_Canvas_DrawImgRect, v);

    RegisterUINutApi(_SC("sq_CreateText"), SQR_CreateText, v);
    RegisterUINutApi(_SC("sq_Text_SetText"), SQR_Text_SetText, v);
}
