#include "core/input/global_inputs.hpp"

#include <SDL3/SDL.h>

#include <string>  // Para allocator, operator+, char_traits, string
#include <vector>  // Para vector

#include "core/input/input.hpp"       // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT
#include "core/rendering/screen.hpp"  // Para Screen
#include "game/options.hpp"           // Para Options, options, OptionsVideo, Section
#include "game/scene_manager.hpp"     // Para SceneManager
#include "game/ui/notifier.hpp"       // Para Notifier, NotificationText
#include "utils/utils.hpp"            // Para stringInVector

#ifdef _DEBUG
#include "core/system/debug.hpp"  // Para Debug
#endif

namespace GlobalInputs {

// Funciones internas
namespace {
void handleQuit() {
    const std::string CODE = SceneManager::current == SceneManager::Scene::GAME ? "PRESS AGAIN TO RETURN TO MENU" : "PRESS AGAIN TO EXIT";
    auto code_found = stringInVector(Notifier::get()->getCodes(), CODE);
    if (code_found) {
        // Si la notificación de salir está activa, cambia de sección
        switch (SceneManager::current) {
            case SceneManager::Scene::GAME:
                SceneManager::current = SceneManager::Scene::TITLE;
                break;
            default:
                SceneManager::current = SceneManager::Scene::QUIT;
                break;
        }
    } else {
        // Si la notificación de salir no está activa, muestra la notificación
        Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE);
    }
}

void handleSkipSection() {
    switch (SceneManager::current) {
        case SceneManager::Scene::LOGO:
        case SceneManager::Scene::LOADING_SCREEN:
        case SceneManager::Scene::CREDITS:
        case SceneManager::Scene::DEMO:
        case SceneManager::Scene::GAME_OVER:
        case SceneManager::Scene::ENDING:
        case SceneManager::Scene::ENDING2:
            SceneManager::current = SceneManager::Scene::TITLE;
            SceneManager::options = SceneManager::Options::NONE;
            break;

        default:
            break;
    }
}

void handleToggleBorder() {
    Screen::get()->toggleBorder();
    Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")});
}

void handleToggleVideoMode() {
    Screen::get()->toggleVideoMode();
    Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")});
}

void handleDecWindowZoom() {
    if (Screen::get()->decWindowZoom()) {
        Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
    }
}

void handleIncWindowZoom() {
    if (Screen::get()->incWindowZoom()) {
        Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
    }
}

void handleToggleShaders() {
    Screen::get()->toggleShaders();
    Notifier::get()->show({"SHADERS " + std::string(Options::video.shaders ? "ENABLED" : "DISABLED")});
}

void handleNextPalette() {
    Screen::get()->nextPalette();
    Notifier::get()->show({"PALETTE " + Options::video.palette});
}

void handlePreviousPalette() {
    Screen::get()->previousPalette();
    Notifier::get()->show({"PALETTE " + Options::video.palette});
}

void handleToggleIntegerScale() {
    Screen::get()->toggleIntegerScale();
    Screen::get()->setVideoMode(Options::video.fullscreen);
    Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")});
}

void handleToggleVSync() {
    Screen::get()->toggleVSync();
    Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")});
}

#ifdef _DEBUG
void handleShowDebugInfo() {
    Screen::get()->toggleDebugInfo();
}

/*
void handleToggleDebug() {
    Debug::get()->toggleEnabled();
    Notifier::get()->show({"DEBUG  " + std::string(Debug::get()->isEnabled() ? "ENABLED" : "DISABLED")}, Notifier::TextAlign::CENTER);
}
*/
#endif

// Detecta qué acción global ha sido presionada (si alguna)
auto getPressedAction() -> InputAction {
    if (Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::EXIT;
    }
    if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::ACCEPT;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_BORDER, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_BORDER;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_FULLSCREEN, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_FULLSCREEN;
    }
    if (Input::get()->checkAction(InputAction::WINDOW_DEC_ZOOM, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::WINDOW_DEC_ZOOM;
    }
    if (Input::get()->checkAction(InputAction::WINDOW_INC_ZOOM, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::WINDOW_INC_ZOOM;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_SHADERS, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_SHADERS;
    }
    if (Input::get()->checkAction(InputAction::NEXT_PALETTE, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::NEXT_PALETTE;
    }
    if (Input::get()->checkAction(InputAction::PREVIOUS_PALETTE, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::PREVIOUS_PALETTE;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_INTEGER_SCALE, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_INTEGER_SCALE;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_VSYNC, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_VSYNC;
    }
    if (Input::get()->checkAction(InputAction::TOGGLE_DEBUG, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::TOGGLE_DEBUG;
    }
    if (Input::get()->checkAction(InputAction::SHOW_DEBUG_INFO, Input::DO_NOT_ALLOW_REPEAT)) {
        return InputAction::SHOW_DEBUG_INFO;
    }
    return InputAction::NONE;
}

}  // namespace

// Funciones públicas

// Comprueba los inputs que se pueden introducir en cualquier sección del juego
void handle() {
    // Detectar qué acción global está siendo presionada
    InputAction action = getPressedAction();

    // Ejecutar el handler correspondiente usando switch statement
    switch (action) {
        case InputAction::EXIT:
            handleQuit();
            break;

        case InputAction::ACCEPT:
            handleSkipSection();
            break;

        case InputAction::TOGGLE_BORDER:
            handleToggleBorder();
            break;

        case InputAction::TOGGLE_FULLSCREEN:
            handleToggleVideoMode();
            break;

        case InputAction::WINDOW_DEC_ZOOM:
            handleDecWindowZoom();
            break;

        case InputAction::WINDOW_INC_ZOOM:
            handleIncWindowZoom();
            break;

        case InputAction::TOGGLE_SHADERS:
            handleToggleShaders();
            break;

        case InputAction::NEXT_PALETTE:
            handleNextPalette();
            break;

        case InputAction::PREVIOUS_PALETTE:
            handlePreviousPalette();
            break;

        case InputAction::TOGGLE_INTEGER_SCALE:
            handleToggleIntegerScale();
            break;

        case InputAction::TOGGLE_VSYNC:
            handleToggleVSync();
            break;

        case InputAction::TOGGLE_DEBUG:
            //handleToggleDebug();
            break;

#ifdef _DEBUG
        case InputAction::SHOW_DEBUG_INFO:
            handleShowDebugInfo();
            break;
#endif

        case InputAction::NONE:
        default:
            // No se presionó ninguna acción global
            break;
    }
}
}  // namespace GlobalInputs