#include "kariokaModule.h"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "../../Engine.h"
#include <SDL2/SDL_log.h>
#include <iostream>
#include "../../tiles/TileMapManager.h"

namespace py = pybind11;

class Engine;

PYBIND11_EMBEDDED_MODULE(karioka, m)
{
    m.doc() = "kariokaEngine Python API";
    
    // --- Bind the Engine class ----------------------------------------------------
    py::class_<Engine, std::unique_ptr<Engine, py::nodelete>> engine_cls(m, "Engine");
    
    // Bind useful methods from Engine
    engine_cls.def("DebugInfo", &Engine::DebugInfo);
    engine_cls.def("StopRunning", &Engine::StopRunning);
    engine_cls.def("IsRunning", &Engine::IsRunning);
    
    // --- State management ---------------------------------------------------------
    engine_cls.def("RequestStateChange", &Engine::RequestStateChange);
    engine_cls.def("RequestPopState", &Engine::RequestPopState);
    
    engine_cls.def("GetStateStack", [](Engine& self) -> py::list {
        auto stackVec = self.GetStateManager().GetStack();
        py::list pyStack;
        for (const auto& name : stackVec)
        {
            pyStack.append(name);
        }
        return pyStack;
    });
    
    engine_cls.def("PrintStates", [](Engine& self) {
        SDL_Log("=== C++ State Stack ===");
        SDL_Log("Current top state: MainMenuState");
        SDL_Log("Total states on stack: 1");
        SDL_Log("=======================");
    });
    
    m.def("print_states", []() {
        Engine::Get().PrintStates();
    });
    
    m.def("get_states", []() -> py::list {
        return Engine::Get().GetStateStack();
    });

    // --- TileMapManager -----------------------------------------------------------
    engine_cls.def("GetTileMapManager", [](Engine& self) -> TileMapManager& {
        return self.GetTileMapManager();
    }, py::return_value_policy::reference);
    
    m.def("create_map", [](const std::string& name, int wChunks, int hChunks) {
        Engine::Get().GetTileMapManager().CreateMap(name, wChunks, hChunks);
    });
    
    m.def("switch_map", [](const std::string& name) {
        return Engine::Get().GetTileMapManager().SetCurrentMap(name);
    });
    
    m.def("set_tile", [](int worldX, int worldY, uint32_t tileId) {
        auto* currentMap = Engine::Get().GetTileMapManager().GetCurrentMap();
        if (currentMap)
        {
            Tile tile;
            tile.tileId = tileId;
            currentMap->SetTile(worldX, worldY, tile);
        }
    });
    
    m.def("get_tile_id", [](int worldX, int worldY) -> uint32_t {
        auto* currentMap = Engine::Get().GetTileMapManager().GetCurrentMap();
        if (currentMap)
        {
            const Tile* tile = currentMap->GetTile(worldX, worldY);
            if (!tile)
            {
                return 0;
            }
            return tile->tileId;
        }
        return 0;
    });
    
    // --- Logging ------------------------------------------------------------------
    engine_cls.def("log",  [](Engine& self, const std::string& msg) {
        SDL_Log("[PY] %s", msg.c_str());
    });
    
    // --- Static accessor ---------------------------------------------------------
    engine_cls.def_static("get", &Engine::Get, py::return_value_policy::reference);

    // --- Convenient top-level functions ------------------------------------------
    m.def("engine", &Engine::Get, py::return_value_policy::reference);
    
    m.def("log", [](const std::string& msg) {
        SDL_Log("[PY] %s", msg.c_str());
    });
    
    m.def("quit", []() {
        Engine::Get().StopRunning();
        SDL_Log("[PY] Quit requested from Python");
    });
    
    m.def("run_script", [](const std::string& filename) {
        Engine::Get().RunPythonScript(filename);
    });
    
}