#include "lua_wraper.h"

void LuaDelegate::Stop()
{

}

int LuaDelegate::DoString(std::string scr) {
    if (mVM != nullptr){
        int ret = luaL_dostring(mVM,scr.c_str());
        if (ret > 0){
            printf("lua error");
            PrintError(mVM);
            return -1;
        }
    }
    this->mScript = scr;
    return 0;
}

/*
return:
 -1: error
  0: success
*/
int LuaDelegate::UpdateScript(std::string scr) {
	auto tmp = luaL_newstate();		//打开lua
	if (nullptr == tmp) {
		return -1;
	}
	luaL_openlibs(tmp);					//打开标准库

	int ret = luaL_dostring(tmp, scr.c_str());
	if (ret > 0) {
		printf("UpdateScript error\r\n");
		PrintError(tmp);
		return -1;
	}

    if(nullptr != mVM){
        lua_close(mVM);
    }
    mVM = tmp;
	for (auto x : mFunc) {
		lua_register(mVM, x.first.c_str(), x.second);
	}
	mScript = scr;

    /*
    mScript = scr;
	ret = luaL_dostring(mVM, scr.c_str());
	if (ret > 0) {
		PrintError(mVM);
		return -1;
	}
    */
    return 0;
}

lua_State* LuaDelegate::VM()
{
    return mVM;
}

void LuaDelegate::PrintError(lua_State *L) {
    auto err = std::string("\nFATAL ERROR:%s\n\n") +  lua_tostring(L, -1);
    std::cout << err;
}

int LuaDelegate::BindFunction(std::string name, lua_CFunction function)
{
    if ((nullptr == function) || (name == ""))
        return -1;
    this->mFunc[name] =  function;
	lua_register(mVM, name.c_str(), function);
    return 0;
}

void LuaDelegate::OnSerialData(std::string data) {
	int i = lua_getglobal(mVM, "OnUartData");
	if (i == 0) {
		std::cout << "OnUartData not found\r\n";
		return;
	}
	lua_pushstring(mVM, data.data());
	lua_call(mVM, 1, 0);
}

void LuaDelegate::DumpStack() {
    static int count = 0;
    printf("begin dump lua stack:%d\n", count);
    int top = lua_gettop(mVM);
    for (int i = top; i > 0; --i)
    {
        int t = lua_type(mVM, i);
        switch (t)
        {
        case LUA_TSTRING:
            std::cout<<("%s\n", lua_tostring(mVM, i));
            break;
        case LUA_TBOOLEAN:
            std::cout<<(lua_toboolean(mVM, i) ? "true\n" : "false\n");
            break;
        case LUA_TNUMBER:
            std::cout<<("%g\n", lua_tonumber(mVM, i));
            break;
        default:
            std::cout<<("%s\n", lua_typename(mVM, t));
            break;
        }
    }
    ++count;
}

LuaDelegate::~LuaDelegate() {
    if(nullptr != mVM){
        lua_close(mVM);
    }
}

LuaDelegate::LuaDelegate():
    mVM(nullptr) {
    mVM = luaL_newstate();		//打开lua
    if(nullptr != mVM){
        printf("shit is nullptr");
    }
    luaL_openlibs(mVM);					//打开标准库

}

LuaDelegate::LuaDelegate(std::map<std::string, lua_CFunction> maps) :
	mVM(nullptr) {
	mVM = luaL_newstate();		//打开lua
	if (nullptr != mVM) {
		printf("shit is nullptr");
	}
	luaL_openlibs(mVM);					//打开标准库

    for (auto x : maps) {
		lua_register(mVM, x.first.c_str(), x.second);
    }
    mFunc = maps;
}

int LuaDelegate::DoFile(std::string path) {
    if(mVM != nullptr){
        int ret = luaL_dofile(mVM, path.c_str());
        if (ret > 0){
            printf("lua error");
            return -1;
        }
    }
    return 0;
}