#include "game/scenes/logo.h"

#include <SDL3/SDL.h>

#include <algorithm>  // for min
#include <string>     // for basic_string

#include "core/audio/audio.hpp"          // for Audio::get, Audio::update
#include "core/input/global_inputs.hpp"  // for GlobalInputs::handle
#include "core/input/input.h"            // for Input, REPEAT_FALSE, inputs_e
#include "core/rendering/screen.h"       // for Screen
#include "core/rendering/sprite.h"       // for Sprite
#include "core/rendering/texture.h"      // for Texture
#include "core/resources/asset.h"        // for Asset
#include "core/resources/resource.h"
#include "game/defaults.hpp"  // for bgColor, SECTION_PROG_LOGO, SECTION_PROG...
#include "utils/utils.h"      // for section_t, color_t

// Valores de inicialización y fin
constexpr int INIT_FADE = 100;
constexpr int END_LOGO = 200;

// Constructor
Logo::Logo(SDL_Renderer *renderer, section_t *section) {
    // Copia la dirección de los objetos
    this->renderer = renderer;
    this->section = section;

    // Reserva memoria para los punteros
    eventHandler = new SDL_Event();
    texture = Resource::get()->getTexture("logo.png");
    sprite = new Sprite(14, 75, 226, 44, texture, renderer);

    // Inicializa variables
    counter = 0;
    section->name = SECTION_PROG_LOGO;
    section->subsection = 0;
    ticks = 0;
    ticksSpeed = 15;

    Audio::get()->stopMusic();
}

// Destructor
Logo::~Logo() {
    // texture es propiedad de Resource — no liberar aquí.
    delete sprite;
    delete eventHandler;
}

// Comprueba si ha terminado el logo
void Logo::checkLogoEnd() {
    if (counter >= END_LOGO + 20) {
        section->name = SECTION_PROG_INTRO;
        section->subsection = 0;
    }
}

// Comprueba las entradas
void Logo::checkInput() {
#ifndef __EMSCRIPTEN__
    if (Input::get()->checkInput(input_exit, REPEAT_FALSE)) {
        section->name = SECTION_PROG_QUIT;
        return;
    }
#endif
    if (GlobalInputs::handle()) { return; }

    if (Input::get()->checkInput(input_pause, REPEAT_FALSE) || Input::get()->checkInput(input_accept, REPEAT_FALSE) || Input::get()->checkInput(input_fire_left, REPEAT_FALSE) || Input::get()->checkInput(input_fire_center, REPEAT_FALSE) || Input::get()->checkInput(input_fire_right, REPEAT_FALSE)) {
        section->name = SECTION_PROG_TITLE;
        section->subsection = SUBSECTION_TITLE_1;
    }
}

// Dibuja el fade
void Logo::renderFade() {
    // Dibuja el fade
    if (counter >= INIT_FADE) {
        const float step = (float)(counter - INIT_FADE) / (float)(END_LOGO - INIT_FADE);
        const int alpha = std::min((int)(255 * step), 255);
        SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, alpha);
        SDL_RenderFillRect(renderer, nullptr);
    }
}

// Actualiza las variables del objeto
void Logo::update() {
    Audio::update();
    checkInput();

    if (SDL_GetTicks() - ticks > ticksSpeed) {
        // Actualiza el contador de ticks
        ticks = SDL_GetTicks();

        // Actualiza el contador
        counter++;

        // Comprueba si ha terminado el logo
        checkLogoEnd();
    }
}

// Dibuja el objeto en pantalla
void Logo::render() {
    // Prepara para empezar a dibujar en la textura de juego
    Screen::get()->start();

    // Limpia la pantalla
    Screen::get()->clean({238, 238, 238});

    // Dibuja los objetos
    sprite->render();

    // Dibuja el fade
    renderFade();

    // Vuelca el contenido del renderizador en pantalla
    Screen::get()->blit();
}

// Bucle para el logo del juego
void Logo::run() {
    Audio::get()->stopMusic();

    while (section->name == SECTION_PROG_LOGO) {
        iterate();
    }
}

// Ejecuta un frame
void Logo::iterate() {
    update();
    render();
}

// Procesa un evento individual
void Logo::handleEvent(const SDL_Event *event) {
    // SDL_EVENT_QUIT ya lo maneja Director
}
