#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include <vector>
#include <cstring>
#include <iostream>

template <typename R, typename A, typename... ARG>
R CallUser(A call_addr, const ARG... arguments)
{
    if (!call_addr)
    {
        return R();
    }
    const auto control = reinterpret_cast<R (*)(ARG...)>(call_addr);
    try
    {
        return control(arguments...);
    }
    catch (...)
    {
    }
    return R();
}

typedef int (*__GetUserByThis)(void *CUser);
typedef int (*__GetUserArea)(void *CUser, bool a);
typedef int (*__SetUserByInt)(void *CUser, int Value);
static SQInteger CUser_GetPosX(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger X = int(((__GetUserByThis)0x0813492c)((void *)P));
    sq_pushinteger(v, X);
    return 1;
}
static SQInteger CUser_GetPosY(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Y = int(((__GetUserByThis)0x0813493c)((void *)P));
    sq_pushinteger(v, Y);
    return 1;
}
static SQInteger CUser_Direction(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x0813494c)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetVill(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Vill = int(((__GetUserByThis)0x08645564)((void *)P));
    sq_pushinteger(v, Vill);
    return 1;
}
static SQInteger CUser_GetArea(HSQUIRRELVM v)
{
    SQUserPointer P;
    SQInteger Type = 0;
    sq_getuserpointer(v, 2, &P);
    if (sq_gettop(v) == 3)
    {
        sq_getinteger(v, 3, &Type);
    }
    SQInteger Area = int(((__GetUserArea)0x086813BE)((void *)P, Type));
    sq_pushinteger(v, Area);
    return 1;
}
static SQInteger CUser_GetState(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger State = int(((__GetUserByThis)0x080DA38C)((void *)P));
    sq_pushinteger(v, State);
    return 1;
}
static SQInteger CUser_GetCharacCount(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Count = int(((__GetUserByThis)0x082300E8)((void *)P));
    sq_pushinteger(v, Count);
    return 1;
}
static SQInteger CUser_GetUniqueId(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger UID = int(((__GetUserByThis)0x080DA37C)((void *)P));
    sq_pushinteger(v, UID);
    return 1;
}
static SQInteger CUser_GetAccId(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger UID = int(((__GetUserByThis)0x080DA36E)((void *)P));
    sq_pushinteger(v, UID);
    return 1;
}
static SQInteger CUser_GetCharacNo(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger CID = int(((__GetUserByThis)0x080CBC4E)((void *)P));
    sq_pushinteger(v, CID);
    return 1;
}
static SQInteger CUser_GetCharacJob(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x080FDF20)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetCharacName(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x08101028)((void *)P));
    sq_pushstring(v, _SC((char *)Ret), -1);
    return 1;
}
static SQInteger CUser_GetCharacLevel(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x080DA2B8)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_SetCharacLevel(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Value;
    sq_getinteger(v, 3, &Value);
    ((__SetUserByInt)0x0867a95c)((void *)P, Value);
    return 0;
}
static SQInteger CUser_GetCharacGrowType(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x0815741C)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetCharacSecondGrowType(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x0822F23C)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetFatigue(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x08657766)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetMaxFatigue(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x08657804)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
typedef int (*__CUser_DisConnSig)(void *CUser, int type, int is, int err);
static SQInteger CUser_DisConnSig(HSQUIRRELVM v)
{
    SQUserPointer P;
    SQInteger Src;
    SQInteger P2;
    SQInteger P3;
    sq_getuserpointer(v, 2, &P);
    sq_getinteger(v, 3, &Src);
    sq_getinteger(v, 4, &P2);
    sq_getinteger(v, 5, &P3);
    SQInteger Ret = int(((__CUser_DisConnSig)0x086489F4)((void *)P, Src, P2, P3));
    sq_pushinteger(v, Ret);
    return 1;
}
typedef void *(*__GetUserParty)(void *CUser);
static SQInteger CUser_GetParty(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQUserPointer Ret = (((__GetUserParty)0x0865514C)((void *)P));
    sq_pushuserpointer(v, Ret);
    return 1;
}
static SQInteger CUser_CheckInBossTower(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x082a67e2)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_CheckInBlueMarble(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x080da32a)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_IsGmMode(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x0814589c)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetVisibleValues(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x0868BDE4)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
static SQInteger CUser_GetCurCharacLastPlayTick(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Ret = int(((__GetUserByThis)0x082A66AA)((void *)P));
    sq_pushinteger(v, Ret);
    return 1;
}
typedef int (*__GiveUserItem)(void *CUser, int a2, int a3, int a4, int *a5, int a6);
typedef int (*__UserSendUpdateItemList)(void *CUser, int a2, int a3, int a4);
static SQInteger CUser_GiveUserItem(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger ItemId, ItemCount;
    sq_getinteger(v, 3, &ItemId);
    sq_getinteger(v, 4, &ItemCount);
    int *ItemSpace = (int *)malloc(4);
    int Slot = int(((__GiveUserItem)0x0867B6D4)((void *)P, ItemId, ItemCount, 6, ItemSpace, 0));
    if (Slot >= 0)
    {
        sq_newarray(v, 0);
        sq_pushinteger(v, *ItemSpace);
        sq_arrayappend(v, -2);
        sq_pushinteger(v, Slot);
        sq_arrayappend(v, -2);
    }
    else
        sq_pushnull(v);
    return 1;
}
// 通知客户端更新道具信息
static SQInteger CUser_SendUpdateItemList(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Type, ItemSpace, Slot;
    sq_getinteger(v, 3, &Type);
    sq_getinteger(v, 4, &ItemSpace);
    sq_getinteger(v, 5, &Slot);

    CallUser<int>(0x867C65A, P, Type, ItemSpace, Slot);
    return 0;
}
// 通知客户端更新背包栏
static SQInteger CUser_SendItemSpace(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger itemSpace;
    sq_getinteger(v, 3, &itemSpace);

    std::cout << *(int *)P << std::endl;
    CallUser<int>(0x865DB6C, P, itemSpace);
    return 0;
}
// 发送邮件
static SQInteger CUser_SendMail(HSQUIRRELVM v)
{
    SQInteger Cid;
    sq_getinteger(v, 2, &Cid);

    std::vector<std::pair<int, int>> List;
    List.clear();

    int ItemListLen = 0;
    sq_pushnull(v); // null iterator
    while (SQ_SUCCEEDED(sq_next(v, 3)))
    {
        SQInteger Index, Count;
        sq_getinteger(v, -1, &Count);
        sq_getinteger(v, -2, &Index);
        std::pair<int, int> pair1 = std::make_pair(Index, Count);
        List.push_back(pair1);
        // 这里-1是值，-2是键
        sq_pop(v, 2); // 在下一次迭代之前弹出键和值
        ItemListLen++;
    }
    sq_pop(v, 1);

    void *addition_slots = malloc(1000);
    for (int i = 0; i < 10; i++)
    {
        CallUser<void>(0x80CB854, addition_slots + (i * 61));
    }
    CallUser<int>(0x8556A14, List, addition_slots, 10);

    SQInteger Gold;
    sq_getinteger(v, 4, &Gold);
    const SQChar *Title;
    const SQChar *Text;
    sq_getstring(v, 5, &Title);
    sq_getstring(v, 6, &Text);
    int TextLen = strlen(Text);

    CallUser<int>(0x8556B68, Title, addition_slots, ItemListLen, Gold, Cid, Text, TextLen, 0, 99, 1);
    return 0;
}
// 发送邮件
static SQInteger CUser_ChangeGrowType(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Base, Ex;
    sq_getinteger(v, 3, &Base);
    sq_getinteger(v, 4, &Ex);

    CallUser<int>(0x867B048, P, Base, Ex);
    return 0;
}

// 发送消息包
static SQInteger CUser_SendNotiPacket(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Type1, Type2, Type3;
    sq_getinteger(v, 3, &Type1);
    sq_getinteger(v, 4, &Type2);
    sq_getinteger(v, 5, &Type3);
    CallUser<int>(0x867BA5C, P, Type1, Type2, Type3);
    return 0;
}
// 获取技能树
static SQInteger CUser_GetSkillW(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    void *S = CallUser<void *>(0x822F140, P);
    sq_pushuserpointer(v, S);
    return 1;
}
// 重置技能
static SQInteger CUser_InitSkillW(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger GrowType, IsAwa;
    sq_getinteger(v, 3, &GrowType);
    sq_getinteger(v, 4, &IsAwa);
    CallUser<int>(0x8608120, P, GrowType, IsAwa);
    return 0;
}
// 改变GM完成任务模式
static SQInteger CUser_ChangeGmQuestFlag(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Type;
    sq_getinteger(v, 3, &Type);

    CallUser<int>(0x822FC8E, P, Type);
    return 0;
}
// 任务相关操作
static SQInteger CUser_QuestAction(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    SQInteger Type, QuestId, Reward, Flag;
    sq_getinteger(v, 3, &Type);
    sq_getinteger(v, 4, &QuestId);
    sq_getinteger(v, 5, &Reward);
    sq_getinteger(v, 6, &Flag);

    CallUser<int>(0x0866DA8A, P, Type, QuestId, Reward, Flag);
    return 0;
}
// 刷新上次任务完成时间
static SQInteger CUser_RefreshLastQuestTime(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);

    *(int *)((void *)P + 0x79644) = 0;
    return 0;
}
// 充值点券
static SQInteger CUser_RechargeCoupons(HSQUIRRELVM v)
{
    SQUserPointer User;
    sq_getuserpointer(v, 2, &User);
    SQInteger Amount;
    sq_getinteger(v, 3, &Amount);
    CallUser<int>(0x80FFCA4, *(uintptr_t *)0x941F734, User, 5, Amount, (void *)0x8C7FA20, (void *)0x8C7FA20, "Gm", (void *)0, (void *)0, (void *)0);

    CallUser<int>(0x8100790, *(uintptr_t *)0x941F734, User);
    return 0;
}
// 充值代币券
static SQInteger CUser_RechargeCouponsPoint(HSQUIRRELVM v)
{
    SQUserPointer User;
    sq_getuserpointer(v, 2, &User);
    SQInteger Amount;
    sq_getinteger(v, 3, &Amount);
    CallUser<int>(0x80FFFC0, *(uintptr_t *)0x941F734, User, Amount, 4, (void *)0, (void *)0);

    CallUser<int>(0x8100790, *(uintptr_t *)0x941F734, User);
    return 0;
}
// 充值金币
static SQInteger CUser_RechargeMoney(HSQUIRRELVM v)
{
    SQUserPointer User;
    sq_getuserpointer(v, 2, &User);
    SQInteger Amount;
    sq_getinteger(v, 3, &Amount);
    CallUser<int>(0x84FF29C, User, Amount, 0, 0, 0);

    return 0;
}

static SQInteger register_User_func(HSQUIRRELVM v, SQFUNCTION f, const char *fname)
{
    sq_pushroottable(v);
    sq_pushstring(v, fname, -1);
    sq_newclosure(v, f, 0); // create a new function
    sq_newslot(v, -3, SQFalse);
    sq_pop(v, 1); // pops the root table
}

static void RegisterUser(HSQUIRRELVM v)
{
    // 获取X坐标
    register_User_func(v, CUser_GetPosX, "Sq_CUser_GetPosX");
    // 获取Y坐标
    register_User_func(v, CUser_GetPosY, "Sq_CUser_GetPosY");
    // 获取朝向
    register_User_func(v, CUser_Direction, "Sq_CUser_Direction");
    // 获取城镇编号
    register_User_func(v, CUser_GetVill, "Sq_CUser_GetTownIndex");
    // 获取区域编号
    register_User_func(v, CUser_GetArea, "Sq_CUser_GetAreaIndex");
    // 获取账号状态
    register_User_func(v, CUser_GetState, "Sq_CUser_GetState");
    // 获取角色数量
    register_User_func(v, CUser_GetCharacCount, "Sq_CUser_GetCharacCount");
    // 获取UID
    register_User_func(v, CUser_GetAccId, "Sq_CUser_GetAccId");
    // 获取UniqueId
    register_User_func(v, CUser_GetUniqueId, "Sq_CUser_GetUniqueId");
    // 获取CID
    register_User_func(v, CUser_GetCharacNo, "Sq_CUser_GetCharacNo");
    // 获取角色职业
    register_User_func(v, CUser_GetCharacJob, "Sq_CUser_GetCharacJob");
    // 获取角色名称
    register_User_func(v, CUser_GetCharacName, "Sq_CUser_GetCharacName");
    // 获取角色等级
    register_User_func(v, CUser_GetCharacLevel, "Sq_CUser_GetCharacLevel");
    // 设置角色等级
    register_User_func(v, CUser_SetCharacLevel, "Sq_CUser_SetCharacLevel");
    // 获取角色转职职业
    register_User_func(v, CUser_GetCharacGrowType, "Sq_CUser_GetCharacGrowType");
    // 获取角色觉醒职业
    register_User_func(v, CUser_GetCharacSecondGrowType, "Sq_CUser_GetCharacSecondGrowType");
    // 获取已用疲劳值
    register_User_func(v, CUser_GetFatigue, "Sq_CUser_GetFatigue");
    // 获取最大疲劳值
    register_User_func(v, CUser_GetMaxFatigue, "Sq_CUser_GetMaxFatigue");
    // 踢人
    register_User_func(v, CUser_DisConnSig, "Sq_CUser_DisConnSig");
    // 获取当前小队/副本
    register_User_func(v, CUser_GetParty, "Sq_CUser_GetParty");
    // 获是否在领主塔
    register_User_func(v, CUser_CheckInBossTower, "Sq_CUser_CheckInBossTower");
    // 获取是否在龙之路
    register_User_func(v, CUser_CheckInBlueMarble, "Sq_CUser_CheckInBlueMarble");
    // 是否开启GM权限
    register_User_func(v, CUser_IsGmMode, "Sq_CUser_IsGmMode");
    // 获取可见Values
    register_User_func(v, CUser_GetVisibleValues, "Sq_CUser_GetVisibleValues");
    // 获取账号上次退出游戏的时间
    register_User_func(v, CUser_GetCurCharacLastPlayTick, "Sq_CUser_GetCurCharacLastPlayTick");
    // 发送道具
    register_User_func(v, CUser_GiveUserItem, "Sq_CUser_GiveUserItem");
    // 通知客户端更新背包
    register_User_func(v, CUser_SendItemSpace, "Sq_CUser_SendItemSpace");
    // 通知客户端道具更新
    register_User_func(v, CUser_SendUpdateItemList, "Sq_CUser_SendUpdateItemList");
    // 发送GM邮件
    register_User_func(v, CUser_SendMail, "Sq_CUser_SendMail");
    // 更改职业
    register_User_func(v, CUser_ChangeGrowType, "Sq_CUser_ChangeGrowType");
    // 发送消息包
    register_User_func(v, CUser_SendNotiPacket, "Sq_CUser_SendNotiPacket");
    // 获取技能树
    register_User_func(v, CUser_GetSkillW, "Sq_CUser_GetSkillW");
    // 重置技能树
    register_User_func(v, CUser_InitSkillW, "Sq_CUser_InitSkillW");
    // 改变GM完成任务模式
    register_User_func(v, CUser_ChangeGmQuestFlag, "Sq_CUser_ChangeGmQuestFlag");
    // 任务相关操作
    register_User_func(v, CUser_QuestAction, "Sq_CUser_QuestAction");
    // 刷新上次任务完成时间
    register_User_func(v, CUser_RefreshLastQuestTime, "Sq_CUser_RefreshLastQuestTime");
    // 充值点券
    register_User_func(v, CUser_RechargeCoupons, "Sq_CUser_RechargeCoupons");
    // 充值代币券
    register_User_func(v, CUser_RechargeCouponsPoint, "Sq_CUser_RechargeCouponsPoint");
    // 充值金币
    register_User_func(v, CUser_RechargeMoney, "Sq_CUser_RechargeMoney");
}