#pragma once
#include "squirrel.h"
#include "sqstdaux.h"
#include "sqstdblob.h"
#include "sqstdio.h"
#include "sqstdmath.h"
#include "sqstdstring.h"
#include "sqstdsystem.h"
#include "CConnectPool.h"
#include "inline_hook.h"

#include <iostream>
#include <functional>
#include <list>
#include <ffi.h>
#include <keystone/keystone.h>

static SQInteger _file_releasehook(SQUserPointer p, SQInteger SQ_UNUSED_ARG(size))
{
    free((void*)p);
    return 0;
}
// 注册析构函数
static SQInteger Register_Destruction(HSQUIRRELVM v)
{
    // 析构函数测试
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);

    sq_setinstanceup(v, 3, P);
    sq_setreleasehook(v, 3, _file_releasehook);
    return 0;
}

static SQInteger PointerOperation(HSQUIRRELVM v)
{
    SQUserPointer Address;
    sq_getuserpointer(v, 2, &Address);
    SQInteger Offset;
    sq_getinteger(v, 3, &Offset);

    const SQChar* TypecharBuf;
    sq_getstring(v, 4, &TypecharBuf);
    std::string Type(TypecharBuf);

    if (Type == "+")
    {
        sq_pushuserpointer(v, (void*)(Address + Offset));
    }
    else if (Type == "-")
    {
        sq_pushuserpointer(v, (void*)(Address - Offset));
    }

    return 1;
}

static SQInteger PointerOperationPointer(HSQUIRRELVM v)
{
    SQUserPointer Address;
    sq_getuserpointer(v, 2, &Address);
    SQUserPointer Address2;
    sq_getuserpointer(v, 3, &Address2);

    const SQChar* TypecharBuf;
    sq_getstring(v, 4, &TypecharBuf);
    std::string Type(TypecharBuf);

    if (Type == "+")
    {
        sq_pushuserpointer(v, (void*)((int)Address + (int)Address2));
    }
    else if (Type == "-")
    {
        sq_pushuserpointer(v, (void*)((int)Address - (int)Address2));
    }

    return 1;
}

// 写字节数组
static SQInteger Memory_WriteByteArr(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);
    char* Address = (char*)P;

    size_t Idx = 0;
    sq_pushnull(v); // null iterator
    while (SQ_SUCCEEDED(sq_next(v, 3)))
    {
        SQInteger Buf;
        sq_getinteger(v, -1, &Buf);
        CMem::WriteUChar((Address + Idx), Buf);
        // 这里-1是值，-2是键
        sq_pop(v, 2); // 在下一次迭代之前弹出键和值
        Idx++;
    }
    sq_pop(v, 1);

    return 0;
}

static SQInteger Memory_WriteBlob(HSQUIRRELVM v)
{
    SQUserPointer P;
    sq_getuserpointer(v, 2, &P);

    SQUserPointer blob_data;
    SQInteger blob_len = sqstd_getblobsize(v, 3);
    sqstd_getblob(v, 3, &blob_data);

    CMem::WriteBytes(P, blob_data, blob_len);

    return 0;
}

// 读内存字符串
static SQInteger Memory_ReadString(HSQUIRRELVM v)
{
    // 内存地址
    SQUserPointer Address;
    // 获取地址
    sq_getuserpointer(v, 2, &Address);
    if (sq_gettop(v) == 3)
    {
        SQInteger Length;
        sq_getinteger(v, 3, &Length);
        sq_pushstring(v, (char*)(Address), Length);
    }
    else
    {
        sq_pushstring(v, (char*)(Address), -1);
    }
    return 1;
}

// 将汇编代码字符串转为字节码
static SQInteger Asmjit_Compile(HSQUIRRELVM v)
{
    const SQChar* CharBuf;
    sq_getstring(v, 2, &CharBuf);
    std::string AsmCode(CharBuf);
    SQUserPointer Address = 0;
    if (sq_gettop(v) == 3)
    {
        sq_getuserpointer(v, 3, &Address);
    }

    ks_engine* ks;
    ks_err err;
    size_t count;
    unsigned char* encode;
    size_t size;
    // 打开Keystone引擎，使用x86-64架构和Intel语法
    if (ks_open(KS_ARCH_X86, KS_MODE_32, &ks) != KS_ERR_OK)
    {
        // fprintf(stderr, "Failed to open Keystone\n");
        return -1;
    }
    // 可选：设置语法为Intel（默认已经是Intel，可省略）
    ks_option(ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_INTEL);
    // 汇编指令
    if (ks_asm(ks, AsmCode.c_str(), (uint64_t)Address, &encode, &size, &count) != KS_ERR_OK)
    {
        // fprintf(stderr, "Assembly error: %s\n", ks_strerror(ks_errno(ks)));
        ks_close(ks);
        return -1;
    }
    // 创建Squirrel数组
    sq_newarray(v, 0);
    // 将每个字节压入数组
    for (size_t i = 0; i < size; ++i)
    {
        sq_pushinteger(v, encode[i]); // 压入字节值
        sq_arrayappend(v, -2);        // 添加到数组（-2是数组位置）
    }
    // 释放资源
    ks_free(encode);
    ks_close(ks);

    return 1; // 返回1表示有返回值
}

static SQInteger register_Memory_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 RegisterMemory(HSQUIRRELVM v)
{
    // 析构函数
    register_Memory_func(v, Register_Destruction, "Register_Destruction");
    // 运算
    register_Memory_func(v, PointerOperation, "Sq_PointerOperation");
    register_Memory_func(v, PointerOperationPointer, "Sq_PointerOperationPointer");
    // 写字节
    register_Memory_func(v, Memory_WriteByteArr, "Sq_Memory_WriteByteArr");
    // 读字符串
    register_Memory_func(v, Memory_ReadString, "Sq_Memory_ReadString");
    // 将汇编代码字符串转为字节码
    register_Memory_func(v, Asmjit_Compile, "Sq_Asmjit_Compile");
    // 写
    register_Memory_func(v, Memory_WriteBlob, "Sq_Memory_WriteBlob");
}