#include "instructions.h"

const Uint8 SELF = 0;

// Constructor
Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *mAsset, Lang *lang)
{
	// Copia los punteros
	mRenderer = renderer;
	mScreen = screen;
	this->mAsset = mAsset;
	mLang = lang;

	// Reserva memoria para los punteros
	mEventHandler = new SDL_Event();
	mItemTexture = new LTexture(mRenderer,mAsset->get("items.png"));
	mSprite = new Sprite(0, 0, GAME_WIDTH, GAME_HEIGHT, mItemTexture, mRenderer);
	mText = new Text(mAsset->get("smb2.png"), mAsset->get("smb2.txt"), mRenderer);

	// Crea un backbuffer para el renderizador
	mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAME_WIDTH, GAME_HEIGHT);
	if (mBackbuffer == nullptr)
	{
		printf("Backbuffer could not be created!\nSDL Error: %s\n", SDL_GetError());
	}
}

// Destructor
Instructions::~Instructions()
{
	mRenderer = nullptr;
	mScreen = nullptr;
	mAsset = nullptr;
	mLang = nullptr;

	mItemTexture->unload();
	delete mItemTexture;
	mItemTexture = nullptr;

	delete mSprite;
	mSprite = nullptr;

	delete mEventHandler;
	mEventHandler = nullptr;

	delete mText;
	mText = nullptr;

	SDL_DestroyTexture(mBackbuffer);
	mBackbuffer = nullptr;
}

// Inicializa las variables necesarias para la sección 'Instructions'
void Instructions::init()
{
	// Inicializa variables
	mSection.name = SELF;
	mTicks = 0;
	mTicksSpeed = 15;
	mManualQuit = false;
	mCounter = 0;
}

// Bucle para la pantalla de instrucciones
void Instructions::run(Uint8 mode)
{
	init();

	while (mSection.name == SELF)
	{
		// Comprueba los eventos que hay en la cola
		while (SDL_PollEvent(mEventHandler) != 0)
		{
			// Evento de salida de la aplicación
			if (mEventHandler->type == SDL_QUIT)
			{
				mSection.name = PROG_SECTION_QUIT;
				break;
			}

			if ((mEventHandler->type == SDL_KEYDOWN) || (mEventHandler->type == SDL_JOYBUTTONDOWN))
			{
				if (mode == INSTRUCTIONS_MODE_AUTO)
				{
					JA_StopMusic();
					mSection.name = PROG_SECTION_TITLE;
					mSection.subsection = TITLE_SECTION_1;
				}
				else
					mManualQuit = true;
			}
		}

		// Actualiza las variables
		if (SDL_GetTicks() - mTicks > mTicksSpeed)
		{
			// Actualiza el contador de ticks
			mTicks = SDL_GetTicks();

			// Modo automático
			if (mode == INSTRUCTIONS_MODE_AUTO)
			{
				mCounter++;

				if (mCounter == INSTRUCTIONS_COUNTER)
				{
					mSection.name = PROG_SECTION_TITLE;
					mSection.subsection = TITLE_SECTION_1;
				}
			}
			// Modo manual
			else
			{
				++mCounter %= 60000;

				if (mManualQuit)
				{
					mSection.name = PROG_SECTION_TITLE;
					mSection.subsection = TITLE_SECTION_3;
				}
			}
		}

		// Pinta en pantalla
		SDL_Rect window = {0, 0, GAME_WIDTH, GAME_HEIGHT};
		SDL_Rect srcRect = {0, 0, 16, 16};

		const color_t orangeColor = {0xFF, 0x7A, 0x00};

		const SDL_Rect destRect1 = {60, 88 + (16 * 0), 16, 16}; // Disquito
		const SDL_Rect destRect2 = {60, 88 + (16 * 1), 16, 16}; // Gavineixon
		const SDL_Rect destRect3 = {60, 88 + (16 * 2), 16, 16}; // Pacmar
		const SDL_Rect destRect4 = {60, 88 + (16 * 3), 16, 16}; // Time Stopper
		const SDL_Rect destRect5 = {60, 88 + (16 * 4), 16, 16}; // Coffee

		// Pinta en el backbuffer el texto y los sprites
		SDL_SetRenderTarget(mRenderer, mBackbuffer);
		SDL_SetRenderDrawColor(mRenderer, bgColor.r, bgColor.g, bgColor.b, 255);
		SDL_RenderClear(mRenderer);

		// Escribe el texto
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 8, mLang->getText(11), 1, orangeColor, 1, shdwTxtColor);
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 24, mLang->getText(12), 1, noColor, 1, shdwTxtColor);
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 34, mLang->getText(13), 1, noColor, 1, shdwTxtColor);
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 48, mLang->getText(14), 1, noColor, 1, shdwTxtColor);
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 58, mLang->getText(15), 1, noColor, 1, shdwTxtColor);
		mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, 75, mLang->getText(16), 1, orangeColor, 1, shdwTxtColor);

		mText->writeShadowed(84, 92, mLang->getText(17), shdwTxtColor);
		mText->writeShadowed(84, 108, mLang->getText(18), shdwTxtColor);
		mText->writeShadowed(84, 124, mLang->getText(19), shdwTxtColor);
		mText->writeShadowed(84, 140, mLang->getText(20), shdwTxtColor);
		mText->writeShadowed(84, 156, mLang->getText(21), shdwTxtColor);

		if ((mode == INSTRUCTIONS_MODE_MANUAL) && (mCounter % 50 > 14))
			mText->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, SCREEN_CENTER_X, GAME_HEIGHT - 12, mLang->getText(22), 1, orangeColor, 1, shdwTxtColor);

		// Disquito
		mSprite->setPos(destRect1);
		srcRect.x = 0;
		srcRect.y = 16 * (((mCounter + 12) / 36) % 2);
		mSprite->setSpriteClip(srcRect);
		mSprite->render();

		// Gavineixon
		mSprite->setPos(destRect2);
		srcRect.x += srcRect.w;
		srcRect.y = 16 * (((mCounter + 9) / 36) % 2);
		mSprite->setSpriteClip(srcRect);
		mSprite->render();

		// Pacmar
		mSprite->setPos(destRect3);
		srcRect.x += srcRect.w;
		srcRect.y = 16 * (((mCounter + 6) / 36) % 2);
		mSprite->setSpriteClip(srcRect);
		mSprite->render();

		// Time Stopper
		mSprite->setPos(destRect4);
		srcRect.x += srcRect.w;
		srcRect.y = 16 * (((mCounter + 3) / 36) % 2);
		mSprite->setSpriteClip(srcRect);
		mSprite->render();

		// Coffee
		mSprite->setPos(destRect5);
		srcRect.x += (srcRect.w * 2); // Se salta el icono del TNT
		srcRect.y = 16 * (((mCounter + 0) / 36) % 2);
		mSprite->setSpriteClip(srcRect);
		mSprite->render();

		// Cambia el destino de renderizado
		SDL_SetRenderTarget(mRenderer, nullptr);

		// Prepara para empezar a dibujar en la textura de juego
		mScreen->start();

		// Limpia la pantalla
		mScreen->clean(bgColor);

		// Establece la ventana del backbuffer
		if (mode == INSTRUCTIONS_MODE_AUTO)
			window.y = std::max(8, GAME_HEIGHT - mCounter + 100);
		else
			window.y = 0;

		// Copia el backbuffer al renderizador
		SDL_RenderCopy(mRenderer, mBackbuffer, nullptr, &window);

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