/*

Ejemplo de uso de las unidades incluídas en jail_engine
Código fuente creado por JailDesigner

*/

#include <SDL2/SDL.h>
#include <iostream>
#include "units/jail_audio.h"
#include "units/text.h"
#include "units/utils.h"
#include "units/asset.h"
#include "units/movingsprite.h"
#include "units/texture.h"
#include "units/screen.h"

SDL_Event *event;
SDL_Window *window;
SDL_Renderer *renderer;
int ticks = 0;
int ticksSpeed = 15;
int counter = 0;
int gradColorMin = 64;		 // Minimo color más alto del degradado
int gradColorMax = 192;		 // Minimo color más alto del degradado
int gradCurrentColor = 192;	 // Color actual más alto del degradado
int gradBreathDirection = 0; // Indica si gradCurrentColor crece o decrece

int main(int argc, char *argv[])
{

	// Inicializa las opciones
	struct options_t *options = new options_t;
	initOptions(options);
	options->gameWidth = 640;
	options->gameHeight = 480;
	options->console = true;

	// Inicializa la lista de recursos
	Asset *asset = new Asset(argv[0]);
	asset->add("/data/music.ogg", t_music);
	asset->add("/data/sound.wav", t_sound);
	asset->add("/data/smb2.txt", t_font);
	asset->add("/data/smb2.png", t_bitmap);
	asset->add("/data/z80.png", t_bitmap);
	asset->add("/data/notify.png", t_bitmap);
	asset->add("/data/notify.wav", t_sound);
	asset->setVerbose(options->console);
	if (!asset->check())
	{
		exit(EXIT_FAILURE);
	}

	// Inicializa SDL y la ventana
	SDL_Init(SDL_INIT_EVERYTHING);
	window = SDL_CreateWindow("jail_engine_demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, options->gameWidth, options->gameHeight, SDL_WINDOW_SHOWN);
	if (window != nullptr)
	{
		renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
		if (renderer == nullptr)
		{
			exit(EXIT_FAILURE);
		}
	}
	else
	{
		exit(EXIT_FAILURE);
	}
	event = new SDL_Event();

	// Inicializa jail_audio
	JA_Init(48000, AUDIO_S16, 2);

	JA_Music_t *music;
	JA_Sound_t *sound;

	music = JA_LoadMusic(asset->get("music.ogg").c_str());
	sound = JA_LoadSound(asset->get("sound.wav").c_str());
	int volume = 128;

	// Inicializa el objeto screen
	Screen *screen = new Screen(window, renderer, options);
	screen->addNotifier(asset->get("notify.png"), asset->get("smb2.png"), asset->get("smb2.txt"), asset->get("notify.wav"));

	// Inicializa el texto
	Text *text = new Text(asset->get("smb2.txt"), asset->get("smb2.png"), renderer);

	// Inicializa el sprite
	Texture *texture = new Texture(renderer, asset->get("z80.png"));
	MovingSprite *sprite = new MovingSprite();
	sprite->setRenderer(renderer);
	sprite->setTexture(texture);
	sprite->setPosX(140);
	sprite->setPosY(100);
	sprite->setWidth(16);
	sprite->setHeight(32);
	sprite->setSpriteClip({0, 0, 16, 32});
	sprite->setVelX(1);
	sprite->setVelY(2);

	// Bucle principal
	// JA_PlayMusic(music, true);
	bool should_exit = false;
	while (!should_exit)
	{

		// Comprueba el teclado y los eventos
		while (SDL_PollEvent(event))
		{
			if (event->type == SDL_QUIT)
			{
				should_exit = true;
				break;
			}
			if (event->type == SDL_KEYDOWN)
			{
				switch (event->key.keysym.scancode)
				{
				case SDL_SCANCODE_N:
					screen->showNotification("Ejemplo de", "notificacion", 1);
					break;

				default:
					break;
				}
			}
		}

		// Actualiza la lógica del programa
		if (SDL_GetTicks() - ticks > ticksSpeed)
		{
			// Actualiza la variable
			ticks = SDL_GetTicks();

			// Incrementa el contador
			counter++;

			// Actualiza el sprite
			if (sprite->getPosX() + sprite->getWidth() > options->gameWidth or sprite->getPosX() < 0)
			{
				sprite->undoMoveX();
				int spr_direction = 1;
				int spr_force = 1;
				if (sprite->getVelX() > 0)
				{
					spr_direction = -1;
				}
				if (SDL_GetTicks() % 2 == 0)
				{
					spr_force = 2;
				}
				sprite->setVelX(spr_force * spr_direction);
				JA_PlaySound(sound);
			}
			if (sprite->getPosY() + sprite->getHeight() > options->gameHeight or sprite->getPosY() < 0)
			{
				sprite->undoMoveY();
				int spr_direction = 1;
				int spr_force = 1;
				if (sprite->getVelY() > 0)
				{
					spr_direction = -1;
				}
				if (SDL_GetTicks() % 2 == 0)
				{
					spr_force = 2;
				}
				sprite->setVelY(spr_force * spr_direction);
				JA_PlaySound(sound);
			}
			sprite->update();

			// Actualiza el degradado
			if (counter % 1 == 0)
			{
				gradBreathDirection == 0 ? gradCurrentColor-- : gradCurrentColor++;
				if (gradCurrentColor == gradColorMin)
				{
					gradBreathDirection = 1;
				}
				if (gradCurrentColor == gradColorMax)
				{
					gradBreathDirection = 0;
				}
			}
		}

		// Dibuja en pantalla
		screen->start();
		screen->clean();

		// Dibuja un degradado de fondo
		const int gradFirstLine = options->gameHeight / 3;
		const int gradLastLine = options->gameHeight;
		const int gradNumLines = gradLastLine - gradFirstLine;
		const int gradColorFrom = 0;

		for (int i = gradFirstLine; i < gradLastLine; ++i)
		{
			float step = ((float)(i - gradFirstLine) / gradNumLines);
			int color = gradColorFrom + ((gradCurrentColor - gradColorFrom) * step);
			SDL_SetRenderDrawColor(renderer, color, 0x00, 0x00, 0xFF);
			SDL_RenderDrawLine(renderer, 0, i, options->gameWidth, i);
		}

		// Escribe el texto
		text->setZoom(2);
		text->writeCentered(options->gameWidth / 2, text->getCharacterSize(), "Jail Engine DEMO");
		text->disableZoom();
		text->writeCentered(options->gameWidth / 2, text->getCharacterSize() * 6, "Pulsa 'N' para mostrar una notificacion");

		// Dibuja el sprite
		sprite->render();

		// Vuelca el buffer en pantalla
		screen->blit();
	}

	// Finaliza el sprite
	delete sprite;
	delete texture;

	// Finaliza el texto
	delete text;

	// Finaliza el objeto screen
	delete screen;

	// Finaliza jail_audio
	JA_DeleteSound(sound);
	JA_DeleteMusic(music);

	// Finaliza el objeto con la lista de recuros
	delete asset;

	// Finaliza SDL y la ventana
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	delete event;
	SDL_Quit();

	return 0;
}
