#include "logo.h"
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h>	 // Para SDL_GetTicks
#include <SDL2/SDL_video.h>	 // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility>			 // Para move
#include "global_inputs.h"	 // Para check
#include "input.h"			 // Para Input
#include "jail_audio.h"		 // Para JA_StopMusic
#include "param.h"			 // Para Param, ParamGame, param
#include "resource.h"		 // Para Resource
#include "screen.h"			 // Para Screen
#include "section.h"		 // Para Name, name, Options, options
#include "sprite.h"			 // Para Sprite
#include "texture.h"		 // Para Texture

// Constructor
Logo::Logo()
	: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
	  since_sprite_(std::make_unique<Sprite>(since_texture_)),
	  jail_texture_(Resource::get()->getTexture("logo_jailgames.png")),
	  ticks_(0)
{

	// Inicializa variables
	counter_ = 0;
	section::name = section::Name::LOGO;
	dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
	dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
	since_sprite_->setPosition({(param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight()});
	since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
	since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
	since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??

	// Crea los sprites de cada linea
	for (int i = 0; i < jail_texture_->getHeight(); ++i)
	{
		auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
		temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
		const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
		temp->setX(posX);
		temp->setY(dest_.y + i);
		jail_sprite_.push_back(std::move(temp));
	}

	// Inicializa el vector de colores
	color_.push_back(Color(0x00, 0x00, 0x00)); // Black
	color_.push_back(Color(0x00, 0x00, 0xd8)); // Blue
	color_.push_back(Color(0xd8, 0x00, 0x00)); // Red
	color_.push_back(Color(0xd8, 0x00, 0xd8)); // Magenta
	color_.push_back(Color(0x00, 0xd8, 0x00)); // Green
	color_.push_back(Color(0x00, 0xd8, 0xd8)); // Cyan
	color_.push_back(Color(0xd8, 0xd8, 0x00)); // Yellow
	color_.push_back(Color(0xFF, 0xFF, 0xFF)); // Bright white
}

// Destructor
Logo::~Logo()
{
	jail_texture_->setColor(255, 255, 255);
	since_texture_->setColor(255, 255, 255);
}

// Recarga todas las texturas
void Logo::reloadTextures()
{
	jail_texture_->reLoad();
	since_texture_->reLoad();
}

// Comprueba el manejador de eventos
void Logo::checkEvents()
{
	SDL_Event event;
	// Comprueba los eventos que hay en la cola
	while (SDL_PollEvent(&event))
	{
		// Evento de salida de la aplicación
		if (event.type == SDL_QUIT)
		{
			section::name = section::Name::QUIT;
			section::options = section::Options::QUIT_FROM_EVENT;
			break;
		}

		// Comprueba si se ha cambiado el tamaño de la ventana
		else if (event.type == SDL_WINDOWEVENT)
		{
			if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
			{
				reloadTextures();
			}
		}
	}
}

// Comprueba las entradas
void Logo::checkInput()
{
	// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
	if (Input::get()->checkAnyButtonPressed())
	{
		JA_StopMusic();
		section::name = section::Name::TITLE;
		section::options = section::Options::TITLE_1;
		return;
	}

	// Comprueba los inputs que se pueden introducir en cualquier sección del juego
	globalInputs::check();
}

// Gestiona el logo de JAILGAME
void Logo::updateJAILGAMES()
{
	if (counter_ > 30)
	{
		for (int i = 0; i < (int)jail_sprite_.size(); ++i)
		{
			if (jail_sprite_[i]->getX() != dest_.x)
			{
				if (i % 2 == 0)
				{
					jail_sprite_[i]->incX(-SPEED);
					if (jail_sprite_[i]->getX() < dest_.x)
					{
						jail_sprite_[i]->setX(dest_.x);
					}
				}
				else
				{
					jail_sprite_[i]->incX(SPEED);
					if (jail_sprite_[i]->getX() > dest_.x)
					{
						jail_sprite_[i]->setX(dest_.x);
					}
				}
			}
		}
	}
}

// Gestiona el color de las texturas
void Logo::updateTextureColors()
{
	constexpr int inc = 4;

	// Manejo de 'sinceTexture'
	for (int i = 0; i <= 7; ++i)
	{
		if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i)
		{
			since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
		}
	}

	// Manejo de 'jailTexture' y 'sinceTexture' en el fade
	for (int i = 0; i <= 6; ++i)
	{
		if (counter_ == INIT_FADE_COUNTER_MARK + inc * i)
		{
			jail_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
			since_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
		}
	}
}

// Actualiza las variables
void Logo::update()
{
	constexpr int TICKS_SPEED = 15;

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

		// Actualiza el objeto screen
		Screen::get()->update();

		// Comprueba las entradas
		checkInput();

		// Gestiona el logo de JAILGAME
		updateJAILGAMES();

		// Gestiona el color de las texturas
		updateTextureColors();

		// Gestiona el contador y sus eventos
		counter_++;

		// Comprueba si ha terminado el logo
		if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
		{
			section::name = section::Name::INTRO;
		}
	}
}

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

	// Limpia la pantalla
	Screen::get()->clean();

	// Dibuja los sprites
	for (auto &sprite : jail_sprite_)
	{
		sprite->render();
	}

	if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
	{
		since_sprite_->render();
	}

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

// Bucle para el logo del juego
void Logo::run()
{
	// Detiene la música
	JA_StopMusic();

	while (section::name == section::Name::LOGO)
	{
		checkInput();
		update();
		checkEvents(); // Tiene que ir antes del render
		render();
	}
}