#include "global_inputs.h"
#include <string>           // Para operator+, string
#include "input.h"          // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
#include "jail_audio.h"     // Para JA_EnableMusic, JA_EnableSound
#include "lang.h"           // Para getText
#include "notifier.h"       // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h"        // Para Options, OptionsAudio, options, OptionsM...
#include "section.h"        // Para Name, Options, name, options
#include "utils.h"          // Para boolToOnOff, stringInVector
#include "screen.h"

namespace globalInputs
{
    // Variables
    std::vector<int> service_pressed_counter;

    // Inicializa variables
    void init()
    {
        const auto num_inputs = Input::get()->getNumControllers() + 1;
        service_pressed_counter.reserve(num_inputs);
        for (int i = 0; i < num_inputs; ++i)
        {
            service_pressed_counter.push_back(0);
        }
    }

    // Termina
    void quit(section::Options code)
    {
        const std::string exit_code = "QUIT";
        auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
        if (code_found)
        {
            section::name = section::Name::QUIT;
            section::options = code;
        }
        else
        {
#ifdef ARCADE
            const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
            Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
#else
            Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
#endif
        }
    }

    // Reinicia
    void reset()
    {
        section::name = section::Name::INIT;
        Notifier::get()->showText({"Reset"});
    }

    // Activa o desactiva el audio
    void toggleAudio()
    {
        options.audio.enabled = !options.audio.enabled;
        if (options.audio.enabled)
        {
            JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
            JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
        }
        else
        {
            JA_SetMusicVolume(0);
            JA_SetSoundVolume(0);
        }
        Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
    }

    // Comprueba los inputs que se pueden introducir en cualquier sección del juego
    void check()
    {
        // Teclado
        {
#ifndef ARCADE
            // Comprueba el teclado para cambiar entre pantalla completa y ventana
            if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                Screen::get()->toggleVideoMode();
                const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
                Notifier::get()->showText({mode + " mode"});
                return;
            }

            // Comprueba el teclado para decrementar el tamaño de la ventana
            if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                Screen::get()->decWindowSize();
                const std::string size = std::to_string(options.video.window.size);
                Notifier::get()->showText({"Window size x" + size});
                return;
            }

            // Comprueba el teclado para incrementar el tamaño de la ventana
            if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                Screen::get()->incWindowSize();
                const std::string size = std::to_string(options.video.window.size);
                Notifier::get()->showText({"Window size x" + size});
                return;
            }
#endif
            // Salir
            if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                quit(section::Options::QUIT_WITH_KEYBOARD);
                return;
            }

            // Reset
            if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                reset();
                return;
            }

            // Audio
            if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                toggleAudio();
                return;
            }

            // Shaders
            if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                Screen::get()->toggleShaders();
                return;
            }

#ifdef DEBUG
            // Comprueba el teclado para mostrar la información de debug
            if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                Screen::get()->toggleDebugInfo();
                return;
            }
#endif
            // OnScreenHelp
            if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
            {
                service_pressed_counter[0]++;

                if (service_pressed_counter[0] >= 3000)
                {
                    OnScreenHelp::get()->toggleState();
                    service_pressed_counter[0] = 0;
                }
                return;
            }

            service_pressed_counter[0] = 0;
        }

        // Mandos
        {
            for (int i = 0; i < Input::get()->getNumControllers(); ++i)
            {
                // Salir
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
                    Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    quit(section::Options::QUIT_WITH_CONTROLLER);
                    return;
                }

                // Reset
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
                    Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    reset();
                    return;
                }

                // Audio
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
                    Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    toggleAudio();
                    return;
                }

                // Shaders
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
                    Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    Screen::get()->toggleShaders();
                    return;
                }
#ifdef DEBUG
                // Debug Info
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
                    Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    Screen::get()->toggleDebugInfo();
                    return;
                }
#endif
                // OnScreenHelp
                if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
                {
                    service_pressed_counter[i + 1]++;

                    if (service_pressed_counter[i + 1] >= 3000)
                    {
                        OnScreenHelp::get()->toggleState();
                        service_pressed_counter[i + 1] = 0;
                    }
                    return;
                }

                service_pressed_counter[i + 1] = 0;
            }
        }
    }
}