#include "Engine.h"
#include <SDL2/SDL_log.h>
#include <SDL2/SDL_mixer.h>

Engine::Engine()
{
    InitSDL();
    InitImGui();
    InitAudio();
//    InitPython();
    SDL_Log("Engine::Engine()");
}

Engine::~Engine()
{	
    SDL_Log("Engine::~Engine()");
    ImGui_ImplSDLRenderer2_Shutdown();
    ImGui_ImplSDL2_Shutdown();
    ImGui::DestroyContext();

    Mix_CloseAudio();
    
    if (renderer) { SDL_DestroyRenderer(renderer); }
    if (window)   { SDL_DestroyWindow(window); }
    
//    ShutdownPython();
    
    SDL_Quit();
}

void Engine::InitSDL()
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
    {
        SDL_Log("Engine::InitSDL(): %s", SDL_GetError());
        exit(1);
    }

    window = SDL_CreateWindow("kariokaEngine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                              EngineConfig::DEFAULT_WINDOW_WIDTH, EngineConfig::DEFAULT_WINDOW_HEIGHT,
                              SDL_WINDOW_SHOWN);
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
}

void Engine::InitImGui()
{
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    (void)io;
    ImGui::StyleColorsDark();
    ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
    ImGui_ImplSDLRenderer2_Init(renderer);
}

void Engine::InitAudio()
{
    if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
    {
    }
    
    Mix_AllocateChannels(64);
    Mix_VolumeMusic(EngineConfig::DEFAULT_MUSIC_VOLUME);
    Mix_Volume(-1, EngineConfig::DEFAULT_SOUND_VOLUME);
}

void Engine::HandleEvents()
{
    SDL_Event e;
    while (SDL_PollEvent(&e))
    {
        ImGui_ImplSDL2_ProcessEvent(&e);
        if (e.type == SDL_QUIT)
        {
            isRunning = false;
        }
        
        // stateManager.HandleEvents(*this, e);
    }
}

void Engine::Update(float dt)
{
    // stateManager.Update(*this, dt);
}

void Engine::Render()
{
    SDL_RenderClear(renderer);
    
    // stateManager.Render(*this);
    
    ImGui_ImplSDLRenderer2_NewFrame();
    ImGui_ImplSDL2_NewFrame();
    ImGui::NewFrame();
    // stateManager.RenderImGui(*this);
    ImGui::Render();
    ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), renderer);
    
    SDL_RenderPresent(renderer);
}

void Engine::Run()
{
    Uint64 lastTime = SDL_GetPerformanceCounter();
    while (isRunning)
    {
        Uint64 current = SDL_GetPerformanceCounter();
        float dt = (current - lastTime) / static_cast<float>(SDL_GetPerformanceFrequency());
        lastTime = current;
        
        HandleEvents();
        Update(dt);
        Render();
        
        // Safe State Transition
        // ...
    }
}

void Engine::InitPython()
{
    if (pythonInterpreter) { return; }
    
    try
    {
        pythonInterpreter = std::make_unique<py::scoped_interpreter>();
        
        py::module_ sys = py::module_::import("sys");
        auto path = sys.attr("path").cast<py::list>();
        path.append("assets/scripts");
        SDL_Log("Python interpreter initialized");
        RunPythonScript("init.py");
    }
    catch (const py::error_already_set& e)
    {
        SDL_Log("Python initialization failed: %s", e.what());
    }
}

void Engine::ShutdownPython()
{
    if (pythonInterpreter)
    {
        pythonInterpreter.reset();
        SDL_Log("Python interpreter shut down");
    }
}

void Engine::RunPythonScript(const std::string& filename)
{
    try
    {
        py::eval_file(filename);
    }
    catch (const py::error_already_set& e)
    {
        SDL_Log("Python script error in %s:\n%s", filename.c_str(), e.what());
    }
}