// generated by Fast Light User Interface Designer (fluid) version 1.0300

#include "luacpp.h"

namespace lua
{

extern "C"
{
#include <stdarg.h>
#include <string.h>

}

#define DONE_AND_RETURN(x) {ret_val =x; goto done_and_return;}

int Lua::call_va(const char *table, const char *func, const char *sig, ...) {
  va_list vl;
  int narg, nres;  /* number of arguments and results */
  int ret_val = 0;
  va_start(vl, sig);
  if(table){
   lua_getglobal(L, table);
   lua_getfield(L, -1, func);
  } else {
  	lua_getglobal(L, func);  /* get function */
  }
  if(!lua_isfunction(L,-1)) DONE_AND_RETURN(-1);

  /* push arguments */
  narg = 0;
  while (*sig) {  /* push arguments */
  	switch (*sig++) {

  	  case 'd':  /* double argument */
  		lua_pushnumber(L, va_arg(vl, double));
  		break;

  	  case 'i':  /* int argument */
  		lua_pushnumber(L, va_arg(vl, int));
  		break;

  	  case 's':  /* string argument */
  		lua_pushstring(L, va_arg(vl, char *));
  		break;

  	  case '>':
  		goto endwhile;

  	  default:
  		DONE_AND_RETURN(-2);
  	}
  	narg++;
  	luaL_checkstack(L, 1, "too many arguments");
  } endwhile:

  /* do the call */
  nres = strlen(sig);  /* number of expected results */
  if (lua_pcall(L, narg, nres, 0) != 0)  /* do the call */
  	DONE_AND_RETURN(-3);

  /* retrieve results */
  nres = -nres;  /* stack index of first result */
  while (*sig) {  /* get results */
  	switch (*sig++) {

  	  case 'd':  /* double result */
  		if (!lua_isnumber(L, nres))
  		  DONE_AND_RETURN(-10);
  		*va_arg(vl, double *) = lua_tonumber(L, nres);
  		break;

  	  case 'i':  /* int result */
  		if (!lua_isnumber(L, nres))
  		  DONE_AND_RETURN(-11);
  		*va_arg(vl, int *) = (int)lua_tonumber(L, nres);
  		break;

  	  case 's':  /* string result */
  		if (!lua_isstring(L, nres))
  		  DONE_AND_RETURN(-12);
  		*va_arg(vl, const char **) = lua_tostring(L, nres);
  		break;

  	  default:
  			DONE_AND_RETURN(-5);
  	}
  	nres++;
  }
done_and_return:
  va_end(vl);
  return ret_val; //all went ok
}

Lua::Lua() {
  show_error_func = NULL;
  L = lua_open();   /* opens Lua */
  luaL_openlibs(L); /* opens all standard libraries */
  show_error_func = NULL;
}

Lua::~Lua() {
  lua_close(L);
}

void Lua::set_lua_error(lua_show_error_func ef){
    show_error_func = ef;
}

void Lua::show_error(){
    if(show_error_func)
        (*show_error_func)(lua_tostring(L, -1));
}

char * Lua::gsub(const char* src, const char *re, const char *sub) {
  char *ret_value;
  int top = lua_gettop(L); //saves the stack top
  // if(call_va("string","gsub", "sss>s", src, re, sub, &ret_value)) {
  //	ret_value = strdup(ret_value); //allocate a new copy
  // } else ret_value = NULL;
  // lua_settop(L, top);  //returns stack to it's orign
  // return ret_value;
  lua_getglobal(L, "string");
  //if(lua_istable(L,-1))
  lua_getfield(L, -1, "gsub");
  //if(lua_isfunction(L,-1))
  lua_pushstring(L, src);
  lua_pushstring(L, re);
  lua_pushstring(L, sub);
  lua_call(L, 3, 1);
  if (lua_isstring(L, -1)) ret_value = strdup(lua_tostring(L,-1));
  else ret_value = NULL;
  lua_settop(L, top);  //returns stack to it's orign
  return ret_value;
}

int Lua::dostring(const char *script){
    int top = lua_gettop(L); //saves the stack top
    int ret_value = luaL_dostring(L, script);
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

int Lua::loadstring(const char *script){
    int top = lua_gettop(L); //saves the stack top
    int ret_value = luaL_loadstring(L, script);
    if(ret_value) show_error();
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

int Lua::dofile(const char *file_name){
    int top = lua_gettop(L); //saves the stack top
    int ret_value = luaL_dofile(L, file_name);
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

int Lua::loadfile(const char *file_name){
    int top = lua_gettop(L); //saves the stack top
    int ret_value = luaL_loadfile(L, file_name);
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

int Lua::lua_preprocess_file(const char *file_name){
    int top = lua_gettop(L); //saves the stack top
    int ret_value = -1;
    lua_getglobal(L, "preprocess_file");
    if(lua_isfunction(L, -1)){
        lua_pushstring(L, file_name);
        if(!lua_pcall(L, 1, 1, 0) && lua_isnumber(L, -1))
            ret_value = lua_tointeger(L,-1);
    }
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

void Lua::gvar(const char* key, const char *value){
    lua_pushstring(L, value);
    lua_setglobal(L, key);
}

void Lua::gvar(const char* key, int value){
    lua_pushinteger(L, value);
    lua_setglobal(L, key);
}

void Lua::gvar(const char* key, double value){
    lua_pushnumber(L, value);
    lua_setglobal(L, key);
}

char *Lua::gvar_string(const char* key){
    int top = lua_gettop(L); //saves the stack top
    char *ret_value;
    lua_getglobal(L, key);
    if(lua_isstring(L,-1)) ret_value = strdup(lua_tostring(L, -1));
    else ret_value = NULL;
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

double Lua::gvar_float(const char* key){
    int top = lua_gettop(L); //saves the stack top
    double ret_value;
    lua_getglobal(L, key);
    if(lua_isnumber(L,-1)) ret_value = lua_tonumber(L, -1);
    else ret_value = 0;
    lua_settop(L, top);  //returns stack to it's orign
    return ret_value;
}

}
