#ifndef ENGINE
#define ENGINE

/*

	sdl

*/


#include <stdlib.h>
#include <algorithm>
#include <SDL.h>
#include "co.h"
#include "assets/assets.h"

const int SCREEN_WIDTH = 320;
const int SCREEN_HEIGHT = 180;
const int SCREEN_SCALE = 4; // 4 => 1280x720     5=> 1600x900    6=> 1920x1080
const int SCREEN_CENTER_X = SCREEN_WIDTH /2;
const int SCREEN_CENTER_Y = SCREEN_HEIGHT /2;
const int DELAY_SEC = 1000 / 24;

void Crash(char* msg);

SDL_Rect GetRect(SDL_Texture* texture);

enum _BUTTONS
{
	BtnUp,
	BtnDn,
	BtnLt,
	BtnRt,
	BtnEsc,
	SumBtns
};

class Dp
{
	public:
		SDL_Event e;
		SDL_Renderer* renderer;
		SDL_Window* window;
		SDL_Texture** textures;
		SDL_Rect* rects;
		char *Btns; // buttons
		int X;
		int Y;
		void Blit(int image, int x, int y);
		void LoadImage(int image, const char*);
		static Dp Init();
};


template <int IMAGE, class ... DB>
class Background : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db)
	{
		SDL_RenderClear(dp->renderer);
		int x = 0;// dp->S[backgroundX];
		int y = 0;// dp->S[backgroundY];
		dp->Blit(IMAGE, x,y);
		return this;
	}
};

template <class ... DB>
class Background<0,DB...> : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db)
	{
		SDL_RenderClear(dp->renderer);
		return this;
	}
};

template <class ... DB>
class RefreshScreen : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db)
	{
		SDL_RenderPresent(dp->renderer);
		return this;
	}
};

template <class ... DB>
class WaitOne60th : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db)
	{
		SDL_Delay( DELAY_SEC );
		return this;
	}
};

template <class ... DB>
class Quit : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db) 
	{
		free(dp->textures);
		SDL_DestroyWindow( dp->window );
		SDL_Quit();
		exit(0);
		return 0;
	}
};

template <class ... DB>
class KeyToExit : public Co<Dp*,DB...>
{
	Co<Dp*,DB...>* Routine(Dp * dp,DB ... db)
	{
		while( SDL_PollEvent(&(dp->e)) )
		{
			if (dp->e.type == SDL_QUIT)
			{
				return new Quit<DB...>();
			}
			if (dp->e.type == SDL_MOUSEBUTTONDOWN)
			{
				//return 0;
				int x,y;
				SDL_GetMouseState(&x,&y);
			}
			if (dp->e.type == SDL_KEYDOWN)
			{
				switch(dp->e.key.keysym.sym)
				{
					case SDLK_q:
					case SDLK_ESCAPE:
						return new Quit<DB...>();
					case SDLK_UP:
						dp->Btns[BtnUp] = 1;
						break;
					case SDLK_DOWN:
						dp->Btns[BtnDn] = 1;
						break;
					case SDLK_LEFT:
						dp->Btns[BtnLt] = 1;
						break;
					case SDLK_RIGHT:
						dp->Btns[BtnRt] = 1;
						break;
				}
			}
			if (dp->e.type == SDL_KEYUP)
			{
				switch(dp->e.key.keysym.sym)
				{
					case SDLK_q:
					case SDLK_ESCAPE:
						dp->Btns[BtnEsc] = 0;
					case SDLK_UP:
						dp->Btns[BtnUp] = 0;
						break;
					case SDLK_DOWN:
						dp->Btns[BtnDn] = 0;
						break;
					case SDLK_LEFT:
						dp->Btns[BtnLt] = 0;
						break;
					case SDLK_RIGHT:
						dp->Btns[BtnRt] = 0;
						break;
				}
			}
		}

		return this;
	}
};


#endif
