#include "LuaGameModeApi.hpp"
#include "../GameMode.hpp"
#include <OgreLogManager.h>
#include <cstdio>
#include <cstdlib>

namespace editScene
{

// ---------------------------------------------------------------------------
// Lua: ecs.is_editor_mode() -> bool
// ---------------------------------------------------------------------------

static int luaIsEditorMode(lua_State *L)
{
	(void)L;
	lua_pushboolean(L, isEditorMode() ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.is_game_mode() -> bool
// ---------------------------------------------------------------------------

static int luaIsGameMode(lua_State *L)
{
	(void)L;
	lua_pushboolean(L, isGameMode() ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.is_game_playing() -> bool
// ---------------------------------------------------------------------------

static int luaIsGamePlaying(lua_State *L)
{
	(void)L;
	lua_pushboolean(L, isGamePlaying() ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.is_game_menu() -> bool
// ---------------------------------------------------------------------------

static int luaIsGameMenu(lua_State *L)
{
	(void)L;
	lua_pushboolean(L, isGameMenu() ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.is_game_paused() -> bool
// ---------------------------------------------------------------------------

static int luaIsGamePaused(lua_State *L)
{
	(void)L;
	lua_pushboolean(L, isGamePaused() ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.get_game_mode() -> string ("editor" or "game")
// ---------------------------------------------------------------------------

static int luaGetGameMode(lua_State *L)
{
	(void)L;
	switch (getGameMode()) {
	case GameMode::Editor:
		lua_pushstring(L, "editor");
		break;
	case GameMode::Game:
		lua_pushstring(L, "game");
		break;
	}
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.get_game_play_state() -> string ("menu", "playing", or "paused")
// ---------------------------------------------------------------------------

static int luaGetGamePlayState(lua_State *L)
{
	(void)L;
	switch (getGamePlayState()) {
	case GamePlayState::Menu:
		lua_pushstring(L, "menu");
		break;
	case GamePlayState::Playing:
		lua_pushstring(L, "playing");
		break;
	case GamePlayState::Paused:
		lua_pushstring(L, "paused");
		break;
	}
	return 1;
}

// ---------------------------------------------------------------------------
// Lua: ecs.debug_crash("message") -> crashes the application
// ---------------------------------------------------------------------------

static int luaDebugCrash(lua_State *L)
{
	const char *msg = luaL_optstring(L, 1, "debug_crash called");

	// Log the message
	Ogre::LogManager::getSingleton().logMessage("Lua debug_crash: " +
						    Ogre::String(msg));

	// Print to stderr as well
	std::fprintf(stderr, "Lua debug_crash: %s\n", msg);
	std::fflush(stderr);

	// Trigger a deliberate crash
	// Use abort() which is cross-platform and raises SIGABRT
	std::abort();

	return 0;
}

// ---------------------------------------------------------------------------
// Register all game-mode API functions
// ---------------------------------------------------------------------------

void registerLuaGameModeApi(lua_State *L)
{
	// Get or create the "ecs" global table
	lua_getglobal(L, "ecs");
	if (lua_isnil(L, -1)) {
		lua_pop(L, 1);
		lua_newtable(L);
	}

	// Predicates
	lua_pushcfunction(L, luaIsEditorMode);
	lua_setfield(L, -2, "is_editor_mode");

	lua_pushcfunction(L, luaIsGameMode);
	lua_setfield(L, -2, "is_game_mode");

	lua_pushcfunction(L, luaIsGamePlaying);
	lua_setfield(L, -2, "is_game_playing");

	lua_pushcfunction(L, luaIsGameMenu);
	lua_setfield(L, -2, "is_game_menu");

	lua_pushcfunction(L, luaIsGamePaused);
	lua_setfield(L, -2, "is_game_paused");

	// Query functions
	lua_pushcfunction(L, luaGetGameMode);
	lua_setfield(L, -2, "get_game_mode");

	lua_pushcfunction(L, luaGetGamePlayState);
	lua_setfield(L, -2, "get_game_play_state");

	// Debug crash function
	lua_pushcfunction(L, luaDebugCrash);
	lua_setfield(L, -2, "debug_crash");

	// Set the global
	lua_setglobal(L, "ecs");
}

} // namespace editScene
