#include "LuaDialogueApi.hpp"
#include "../systems/DialogueSystem.hpp"
#include <OgreLogManager.h>

namespace editScene
{

// ---------------------------------------------------------------------------
// Helper: read string vector from Lua table
// ---------------------------------------------------------------------------

static std::vector<Ogre::String> readStringVector(lua_State *L, int idx)
{
	std::vector<Ogre::String> result;
	if (!lua_istable(L, idx))
		return result;

	lua_pushnil(L);
	while (lua_next(L, idx) != 0) {
		if (lua_isstring(L, -1))
			result.push_back(lua_tostring(L, -1));
		lua_pop(L, 1);
	}
	return result;
}

// ---------------------------------------------------------------------------
// Lua CFunctions
// ---------------------------------------------------------------------------

static int luaDialogueShow(lua_State *L)
{
	Ogre::String text;
	std::vector<Ogre::String> choices;
	Ogre::String speaker;

	if (lua_gettop(L) >= 1 && lua_isstring(L, 1))
		text = lua_tostring(L, 1);

	if (lua_gettop(L) >= 2 && lua_istable(L, 2))
		choices = readStringVector(L, 2);

	if (lua_gettop(L) >= 3 && lua_isstring(L, 3))
		speaker = lua_tostring(L, 3);

	DialogueSystem::getInstance().show(text, choices, speaker);
	return 0;
}

static int luaDialogueHide(lua_State *L)
{
	(void)L;
	DialogueSystem::getInstance().hide();
	return 0;
}

static int luaDialogueIsActive(lua_State *L)
{
	lua_pushboolean(L, DialogueSystem::getInstance().isActive() ? 1 : 0);
	return 1;
}

static int luaDialogueSelectChoice(lua_State *L)
{
	int index = 0;
	if (lua_gettop(L) >= 1 && lua_isnumber(L, 1))
		index = (int)lua_tonumber(L, 1);
	DialogueSystem::getInstance().selectChoice(index);
	return 0;
}

static int luaDialogueProgress(lua_State *L)
{
	(void)L;
	DialogueSystem::getInstance().progress();
	return 0;
}

static int luaDialogueGetSettings(lua_State *L)
{
	const auto &s = DialogueSystem::getInstance().getSettings();
	lua_newtable(L);
	lua_pushstring(L, s.fontName.c_str());
	lua_setfield(L, -2, "font_name");
	lua_pushnumber(L, s.fontSize);
	lua_setfield(L, -2, "font_size");
	lua_pushnumber(L, s.speakerFontSize);
	lua_setfield(L, -2, "speaker_font_size");
	lua_pushnumber(L, s.backgroundOpacity);
	lua_setfield(L, -2, "background_opacity");
	lua_pushnumber(L, s.boxHeightFraction);
	lua_setfield(L, -2, "box_height_fraction");
	lua_pushnumber(L, s.boxPositionFraction);
	lua_setfield(L, -2, "box_position_fraction");
	return 1;
}

static int luaDialogueSetSettings(lua_State *L)
{
	if (!lua_istable(L, 1))
		return 0;

	auto s = DialogueSystem::getInstance().getSettings();

	if (lua_getfield(L, 1, "font_name"), lua_isstring(L, -1))
		s.fontName = lua_tostring(L, -1);
	lua_pop(L, 1);

	if (lua_getfield(L, 1, "font_size"), lua_isnumber(L, -1))
		s.fontSize = (float)lua_tonumber(L, -1);
	lua_pop(L, 1);

	if (lua_getfield(L, 1, "speaker_font_size"), lua_isnumber(L, -1))
		s.speakerFontSize = (float)lua_tonumber(L, -1);
	lua_pop(L, 1);

	if (lua_getfield(L, 1, "background_opacity"), lua_isnumber(L, -1))
		s.backgroundOpacity = (float)lua_tonumber(L, -1);
	lua_pop(L, 1);

	if (lua_getfield(L, 1, "box_height_fraction"), lua_isnumber(L, -1))
		s.boxHeightFraction = (float)lua_tonumber(L, -1);
	lua_pop(L, 1);

	if (lua_getfield(L, 1, "box_position_fraction"), lua_isnumber(L, -1))
		s.boxPositionFraction = (float)lua_tonumber(L, -1);
	lua_pop(L, 1);

	DialogueSystem::getInstance().setSettings(s);
	return 0;
}

static int luaDialogueSaveSettings(lua_State *L)
{
	const char *path = "dialogue.json";
	if (lua_gettop(L) >= 1 && lua_isstring(L, 1))
		path = lua_tostring(L, 1);
	bool ok = DialogueSystem::getInstance().saveSettings(path);
	lua_pushboolean(L, ok ? 1 : 0);
	return 1;
}

static int luaDialogueLoadSettings(lua_State *L)
{
	const char *path = "dialogue.json";
	if (lua_gettop(L) >= 1 && lua_isstring(L, 1))
		path = lua_tostring(L, 1);
	bool ok = DialogueSystem::getInstance().loadSettings(path);
	lua_pushboolean(L, ok ? 1 : 0);
	return 1;
}

// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------

void registerLuaDialogueApi(lua_State *L)
{
	lua_getglobal(L, "ecs");
	if (lua_isnil(L, -1)) {
		lua_pop(L, 1);
		lua_newtable(L);
	}

	lua_newtable(L);

	lua_pushcfunction(L, luaDialogueShow);
	lua_setfield(L, -2, "show");

	lua_pushcfunction(L, luaDialogueHide);
	lua_setfield(L, -2, "hide");

	lua_pushcfunction(L, luaDialogueIsActive);
	lua_setfield(L, -2, "is_active");

	lua_pushcfunction(L, luaDialogueSelectChoice);
	lua_setfield(L, -2, "select_choice");

	lua_pushcfunction(L, luaDialogueProgress);
	lua_setfield(L, -2, "progress");

	lua_pushcfunction(L, luaDialogueGetSettings);
	lua_setfield(L, -2, "get_settings");

	lua_pushcfunction(L, luaDialogueSetSettings);
	lua_setfield(L, -2, "set_settings");

	lua_pushcfunction(L, luaDialogueSaveSettings);
	lua_setfield(L, -2, "save_settings");

	lua_pushcfunction(L, luaDialogueLoadSettings);
	lua_setfield(L, -2, "load_settings");

	lua_setfield(L, -2, "dialogue");

	lua_setglobal(L, "ecs");
}

} // namespace editScene
