// BlinkGame - Hunt for the Lost Pixels
// an SDL game in honor of the BlinkenArea crew
//
// (C) 2005-06 Rene Schickbauer
//
// See License.txt for licensing information
//
#ifdef NOP_CODE
/*--------------------------------------------------------------------
					CVS AUTO-GENERATED INFO
$Author: cavac $
$Date: 2006/03/02 13:03:41 $
$Name: rel-0-3-patches $
$Revision: 1.2 $
$State: Exp $

$Log: bl_lua.cpp,v $
Revision 1.2  2006/03/02 13:03:41  cavac
Re-formatted all .cpp and .h files a bit to get rid of the TAB/SPACE mess
that makes troubles with XCode's "re-format" feature

Revision 1.1  2006/02/24 18:48:26  cavac
Finally added real scripting support
Added Testlevel (level0) which can be enabled from globals.h

--------------------------------------------------------------------*/
#endif //NOP_CODE

#include "globals.h"
#include "bl_lua.h"
#include "errorhandler.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "bl_lua_bindings.h"

#include <stdarg.h>
#include <string.h>

lua_State* blLUA = NULL;

void blLuaInit(char *fname)
{
	char fullfname[MAX_FNAME_LENGTH];
	sprintf(fullfname, "%s%s", RESPATH, fname);

	// Initialize LUA
	blLUA = lua_open();
	if(!blLUA) {
		DIE(ERROR_LUAINIT, "");
	}

	// Load libraries
	luaopen_base(blLUA);
	luaopen_io(blLUA);
	luaopen_string(blLUA);
	luaopen_math(blLUA);
	blRegisterLuaBindings(blLUA);

	// Load script file
	if(luaL_loadfile(blLUA, fullfname)) {
		DIE(ERROR_LUALOAD, (char *)lua_tostring(blLUA, -1));
	}
	
	// Parse script file (for globals and such)
	if(lua_pcall(blLUA,0,0,0)) {
		DIE(ERROR_LUAPARSE, (char *)lua_tostring(blLUA, -1));
	}
}

void blLuaDeInit()
{
	if(!blLUA) {
		DIE(ERROR_LUANOINIT, "");
	}
	lua_close(blLUA);
	blLUA = NULL;

}

void blLuaCall(char *func, char *sig, ...)
{
	if(!blLUA) {
		DIE(ERROR_LUANOINIT, "");
	}
	
	va_list vl;
	int narg, nres, npopres;
	
	va_start(vl, sig);
	lua_getglobal(blLUA, func);
	
	// push arguments
	narg = 0;
	bool deli = false;
	while(*sig && !deli) {
		switch(*sig) {
			case 'd': // Double
				lua_pushnumber(blLUA, va_arg(vl, double));
				narg++;
				break;
			case 'i': // Int
				lua_pushnumber(blLUA, va_arg(vl, int));
				narg++;
				break;
			case 's': // String
				lua_pushstring(blLUA, va_arg(vl, char *));
				narg++;
				break;
			case '>': // Delimeter for results
				deli = true;
				break;
			default:
				char tmp[20];
				sprintf(tmp, "FORMAT: (%c)", *sig);
				DIE(ERROR_LUAPARAMFORMAT, tmp);
		}
		luaL_checkstack(blLUA, 1, "too many arguments");
		sig++;
	}
	
	// call the function
	npopres = nres = strlen(sig); // number of expected results
	if(lua_pcall(blLUA, narg, nres, 0)) {
		char tmp[200];
		sprintf(tmp, "Func: '%s' / Err: '%s'", func, lua_tostring(blLUA, -1));
		DIE(ERROR_LUACALL, tmp);
	}
	
	// Get results
	nres = -nres; // Stack index of first result
	while(*sig) {
		switch(*sig) {
			case 'd': // double
				if(!lua_isnumber(blLUA, nres)) {
					DIE(ERROR_LUARESULTTYPE, func);
				}
				*va_arg(vl, double *) = lua_tonumber(blLUA, nres);
				break;
			case 'i': // int
				if(!lua_isnumber(blLUA, nres)) {
					DIE(ERROR_LUARESULTTYPE, func);
				}
				*va_arg(vl, int *) = (int)lua_tonumber(blLUA, nres);
				break;
			case 's': // string
				if(!lua_isstring(blLUA, nres)) {
					DIE(ERROR_LUARESULTTYPE, func);
				}
				sprintf(*va_arg(vl, char **), "%s", lua_tostring(blLUA, nres));
				break;
			default:
				char tmp[20];
				sprintf(tmp, "FORMAT: (%c)", *sig);
				DIE(ERROR_LUAPARAMFORMAT, tmp);
		}
		sig++;
	}
	
	va_end(vl);

	while(npopres) {
		lua_pop(blLUA, 1);
		npopres--;
	}
	
}
