#include "game_over.h"

// Constructor
GameOver::GameOver(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *asset, options_t *options)
{
    // Copia los punteros
    this->renderer = renderer;
    this->screen = screen;
    this->resource = resource;
    this->asset = asset;
    this->options = options;

    // Reserva memoria para los punteros a objetos
    eventHandler = new SDL_Event();
    text = new Text(resource->getOffset("smb2.txt"), resource->getTexture("smb2.png"), renderer);
    playerSprite = new AnimatedSprite(renderer, resource->getAnimation("player_game_over.ani"));
    tvSprite = new AnimatedSprite(renderer, resource->getAnimation("tv.ani"));
    music = JA_LoadMusic(asset->get("game_over.ogg").c_str());

    // Inicializa variables
    preCounter = 0;
    counter = 0;
    section.name = SECTION_PROG_GAME_OVER;
    section.subsection = 0;
    ticks = 0;
    ticksSpeed = 15;
    endSection = 400;
    iniFade = 310;
    fadeLenght = 20;
    playerSprite->setPosX(GAMECANVAS_CENTER_X + 10);
    playerSprite->setPosY(GAMECANVAS_CENTER_Y + 10);
    tvSprite->setPosX(GAMECANVAS_CENTER_X - tvSprite->getAnimationClip(0, 0).w - 10);
    tvSprite->setPosY(GAMECANVAS_CENTER_Y + 10);

    // Inicializa el vector de colores
    const std::vector<std::string> colorList = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
    for (auto cl : colorList)
    {
        colors.push_back(stringToColor(options->palette, cl));
    }
    color = colors.back();
}

// Destructor
GameOver::~GameOver()
{
    // Libera la memoria de los objetos
    delete eventHandler;
    delete text;
    delete playerSprite;
    delete tvSprite;
    JA_DeleteMusic(music);
}

// Actualiza el objeto
void GameOver::update()
{
    // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
    if (SDL_GetTicks() - ticks > ticksSpeed)
    {
        // Actualiza el contador de ticks
        ticks = SDL_GetTicks();

        // Comprueba el manejador de eventos
        checkEventHandler();

        // Actualiza el color usado para renderizar los textos e imagenes
        updateColor();

        // Actualiza los contadores
        updateCounters();

        // Actualiza los dos sprites
        playerSprite->update();
        tvSprite->update();
    }
}

// Dibuja el final en pantalla
void GameOver::render()
{
    // Prepara para empezar a dibujar en la textura de juego
    screen->start();

    // Limpia la pantalla
    screen->clean();

    // Escribe el texto de GAME OVER
    text->writeDX(TXT_CENTER | TXT_COLOR, GAMECANVAS_CENTER_X, GAMECANVAS_CENTER_Y - 20, "G A M E   O V E R", 1, color);

    // Dibuja los sprites
    renderSprites();

    // text->write(0, 0, std::to_string(counter));

    // Vuelca el contenido del renderizador en pantalla
    screen->blit();
}

// Comprueba el manejador de eventos
void GameOver::checkEventHandler()
{
    // Comprueba los eventos que hay en la cola
    while (SDL_PollEvent(eventHandler) != 0)
    {
        // Evento de salida de la aplicación
        if (eventHandler->type == SDL_QUIT)
        {
            section.name = SECTION_PROG_QUIT;
            section.subsection = 0;
            break;
        }

        // Comprueba las teclas que se han pulsado
        if ((eventHandler->type == SDL_KEYDOWN && eventHandler->key.repeat == 0) || (eventHandler->type == SDL_JOYBUTTONDOWN))
        {
            switch (eventHandler->key.keysym.scancode)
            {
            case SDL_SCANCODE_ESCAPE:
                section.name = SECTION_PROG_QUIT;
                break;

            case SDL_SCANCODE_B:
                screen->switchBorder();
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F:
                screen->switchVideoMode();
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F1:
                screen->setWindowSize(1);
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F2:
                screen->setWindowSize(2);
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F3:
                screen->setWindowSize(3);
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F4:
                screen->setWindowSize(4);
                resource->reLoadTextures();
                break;

            case SDL_SCANCODE_F5:
                switchPalette();
                break;

            default:
                break;
            }
        }
    }
}

// Bucle principal
section_t GameOver::run()
{
    while (section.name == SECTION_PROG_GAME_OVER)
    {
        update();
        render();
    }

    return section;
}

// Actualiza el color usado para renderizar los textos e imagenes
void GameOver::updateColor()
{
    const int half = endSection / 2;

    if (counter < half)
    {
        //const float step = std::min(std::max(counter, iniFade) - iniFade, fadeLenght) / (float)fadeLenght;
        const float step = std::min(counter, fadeLenght) / (float)fadeLenght;
        const int index = (colors.size() - 1) - int((colors.size() - 1) * step);
        color = colors.at(index);
    }
    else
    {
        const float step = std::min(std::max(counter, iniFade) - iniFade, fadeLenght) / (float)fadeLenght;
        const int index = (colors.size() - 1) * step;
        color = colors.at(index);
    }
}

// Dibuja los sprites
void GameOver::renderSprites()
{
    playerSprite->getTexture()->setColor(color.r, color.g, color.b);
    playerSprite->render();

    tvSprite->getTexture()->setColor(color.r, color.g, color.b);
    tvSprite->render();
}

// Actualiza los contadores
void GameOver::updateCounters()
{
    // Actualiza el contador
    if (preCounter < 50)
    {
        preCounter++;
    }
    else
    {
        counter++;
    }

    // Hace sonar la música
    if (counter == 1)
    {
        JA_PlayMusic(music, 0);
    }

    // Comprueba si ha terminado la sección
    else if (counter == endSection)
    {
        section.name = SECTION_PROG_LOGO;
        section.subsection = SUBSECTION_LOGO_TO_TITLE;
    }
}

// Cambia la paleta
void GameOver::switchPalette()
{
    options->palette = (options->palette == p_zxspectrum) ? p_zxarne : p_zxspectrum;
}