#include "tiled_bg.h"
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_stdinc.h> // for SDL_sinf
#include <stdlib.h>          // for rand
#include "screen.h"          // for Screen
#include "sprite.h"          // for Sprite
#include "texture.h"         // for Texture

// Constructor
Tiledbg::Tiledbg(std::string texturePath, SDL_Rect pos, int mode)
    : texturePath(texturePath), pos(pos), mode(mode)
{
    // Copia los punteros
    renderer = Screen::get()->getRenderer();

    // Crea la textura para el mosaico de fondo
    canvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos.w * 2, pos.h * 2);

    // Inicializa las variables
    init();
}

// Destructor
Tiledbg::~Tiledbg()
{
    SDL_DestroyTexture(canvas);
}

// Inicializa las variables
void Tiledbg::init()
{
    counter = 0;
    if (mode == TILED_MODE_RANDOM)
    {
        mode = rand() % 2;
    }
    tileWidth = 64;
    tileHeight = 64;

    // Rellena la textura con el contenido
    fillTexture();

    // Coloca la ventana que recorre el mosaico de fondo de manera que coincida
    // con el mosaico que hay pintado en el titulo al iniciar
    window.x = 128;
    window.y = 96;
    window.w = pos.w;
    window.h = pos.h;

    // Inicializa los valores del vector con los valores del seno
    for (int i = 0; i < 360; ++i)
    {
        sin[i] = SDL_sinf((float)i * 3.14f / 180.0f);
    }
}

// Rellena la textura con el contenido
void Tiledbg::fillTexture()
{
    // Crea los objetos para pintar en la textura de fondo
    auto bgTileTexture = std::make_shared<Texture>(renderer, texturePath);
    auto tile = std::make_unique<Sprite>((SDL_Rect){0, 0, tileWidth, tileHeight}, bgTileTexture);

    // Prepara para dibujar sobre la textura
    auto temp = SDL_GetRenderTarget(renderer);
    SDL_SetRenderTarget(renderer, canvas);

    // Rellena la textura con el tile
    const auto iMax = pos.w * 2 / tileWidth;
    const auto jMax = pos.h * 2 / tileHeight;
    tile->setSpriteClip(0, 0, tileWidth, tileHeight);
    for (int i = 0; i < iMax; ++i)
    {
        for (int j = 0; j < jMax; ++j)
        {
            tile->setPosX(i * tileWidth);
            tile->setPosY(j * tileHeight);
            tile->render();
        }
    }

    // Vuelve a colocar el renderizador como estaba
    SDL_SetRenderTarget(renderer, temp);

    // Libera la memoria utilizada por los objetos
    bgTileTexture->unload();
}

// Pinta la clase en pantalla
void Tiledbg::render()
{
    SDL_RenderCopy(renderer, canvas, &window, &pos);
}

// Actualiza la lógica de la clase
void Tiledbg::update()
{
    if (mode == TILED_MODE_DIAGONAL)
    { // El tileado de fondo se desplaza en diagonal
        ++window.x %= tileWidth;
        ++window.y %= tileHeight;
    }
    else if (mode == TILED_MODE_CIRCLE)
    { // El tileado de fondo se desplaza en circulo
        ++counter %= 360;
        window.x = 128 + (int(sin[(counter + 270) % 360] * 128));
        window.y = 96 + (int(sin[(360 - counter) % 360] * 96));
    }
}

// Recarga las texturas
void Tiledbg::reLoad()
{
    fillTexture();
}