/** @file luanav.cpp
 *  An implementation of navigation using LUA
 *	@headerfile luanav.h "EANav/luanav.h"
 *	@author Chris Burns (cburns@ea.com)
 *
 *	UX
 *	(c) 2012 Electronic Arts Inc.
 */

#include "EANav/luanav.h"
#include "EABaseTypesLua/EABaseTypesLua.h"
#include "EABaseTypesLua/stackcheck.h"
#include "EABaseTypesLua/datautillua.h"
#include "EABaseTypes/functioncallwrappers.h"
#include "EABaseTypes/functor.h"

#include "coreallocator/icoreallocatormacros.h"

#include "eaassert/eaassert.h"

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"


namespace EA
{
	namespace Nav
	{
		namespace LuaNav
		{
			void Create(lua_State *L, EA::Types::FunctionIn callback, const char *implFileName, const char* rootFileName, EA::Types::ObjectIn let)
			{
				EA::Lua::StackCheck s(L);

				if(0 != luaL_loadstring(L,
					"local callback, implFileName, rootFileName, let = ...\n"
					"\n"
					"requireasync(\n"
					"	function(nav, error)\n"
					"		assert(nav ~= nil, error)\n"
					"		local n = nav:new({ debug = not EA_FINAL, fileName = rootFileName, let = let })\n"
					"\n"
					"		local methods =\n"
					"		{\n"
					"			Load = n.load,\n"
					"			Start = n.start,\n"
					"			Event = n.event,\n"
					"			AddActionHandler = n.addAction,\n"
					"			RemoveActionHandler = n.removeAction,\n"
					"			SetLoadFailureHandler = n.setLoadFailed,\n"
					"			SaveConfiguration = n.saveConfiguration,\n"
					"			LoadConfiguration = n.loadConfiguration,\n"
                	"			AddListener = n.addListener,\n"
					"			RemoveListener = n.removeListener\n"
					"		}\n"
					"\n"
					"		if not EA_FINAL then\n"
					"			methods.GetStates = n.getStates\n"
					"			methods.GetTransitionEvents = n.getTransitionEvents\n"
					"			methods.Auto = n.auto\n"
					"			methods.AddAutoHandler = n.addAutoHandler\n"
					"			methods.RemoveAutoHandler = n.removeAutoHandler\n"
					"			methods.GetConfiguration = n.getConfiguration"
                    "           methods.Reload = n.reload"
					"		end\n"
					"\n"
					"		local o = {}\n"
					"		for k, v in pairs(methods) do\n"
					"			o[k] = function(...) return v(n, ...) end\n"
					"		end\n"
					"\n"
					"		callback(o)\n"
					"	end,\n"
					"	implFileName)\n"
					))
				{
					EA_FAIL_MESSAGE(lua_tostring(L, -1));
				}

				EA::Lua::PushBaseType(L, callback);
				lua_pushstring(L, implFileName);
				lua_pushstring(L, rootFileName);
				EA::Lua::PushBaseType(L, let);

				EA::Lua::Call(L, 4, 0);
			}
		}
	}
}
