/*=============================================================================
	  ___________
	 /           \		Par Martin Robinson
	|   @#!$*%    |		logiciel libre GPL
	 \_______   _/
	 		 \ |  ___________
	    	  \| |   O   O   |
				 |  _______  |
				 | | | | | | |
===============================================================================
Preprocesseur
=============================================================================*/

#pragma once
#ifndef spieleUI_deja
#define spieleUI_deja
#include "SDL/SDL.h"
#include "main.hpp"
#include "../lib/sdlMR.hpp"
#include "spiele.hpp"

/*=============================================================================
constante
=============================================================================*/

static const SDL_Rect block = {60,40,SIZE,SIZE},
               casse = {40,40,SIZE,SIZE},
               tapisG = {20,40,SIZE,SIZE},
               tapisD = {0,40,SIZE,SIZE},
			   goal = {80,40,SIZE,SIZE},
			   bg = {100,40,SIZE,SIZE},
			   sprBot = {0,0,SIZE,SIZE},
			   sprTeeth = {0,20,SIZE,SIZE},
			   sprEyes = {20,20,SIZE,SIZE},
			   sprBody = {40,20,SIZE,SIZE},
			   sprShape = {260,20,SIZE,SIZE};

/*============================================================================
objet
============================================================================*/

template < int _LVLW, int _LVLH>
class spieleUI{
	spiele<_LVLW,_LVLH> _spiele;    //la classe spiele qui a déclarer spieleUI comme ami
	SDL_Rect _pos[20];				//liste de rectangle SDL pour positionner l'affichage
	SDL_Surface * _spriteSheet;     //surface sdl ou les sprites sont localisé
	int _col,                       //position horizontale de l'ecran par rapport au level
		_row,                       //position verticale de l'ecran par rapport au level
		_x,                         //coordonné horizontale traduite en pixel
		_y,                         //coordonné verticale traduite en pixel
		_w,                         //largeur de l'ecran
		_h;                         //hauteur de l'ecran
public:
	spieleUI(const char *, const char * thoseShape[9],SDL_Surface * ,const int, const int);					//constructeur
	bool updated();					                //si les animations sont completé
	void update();					                //mettre à jours les rectangles et les animations
    void draw(SDL_Surface * ecran,int,int);	        //dessiner à l'écran
	void control(int);                              //transmettre le controle
	bool process();                                 //activer un cycle de jeux
	bool end();                                     //tester si la partie est terminé
	bool gameover();                                //tester si la partie est échoué
};

/*=========================================================================
fonction
=========================================================================*/

//constructeur
template < int _LVLW, int _LVLH>
spieleUI<_LVLW,_LVLH>::spieleUI(const char * level,const char * thoseShape[9], SDL_Surface * spritesheet,const int w, const int h)
{
	_col = _row = _x = _y = 0;
	_w = w;
	_h = h;
    _spiele.init(level,thoseShape);
	_spriteSheet = spritesheet;
	for (int i=0;i<_spiele._robotQty;i++)    //prepositionner les robots à l'ecran
	{
		_pos[i].w = _pos[i].h = SIZE;
		_pos[i].x = (_spiele._robot[i].col()-_col)*SIZE;
		_pos[i].y = (_spiele._robot[i].row()-_row)*SIZE;
	}
}

//etat de mise à jour graphique
//retourne vrai quand l'animation est terminé
template < int _LVLW, int _LVLH>
bool spieleUI<_LVLW,_LVLH>::updated()
{
	for (int i=0;i<_spiele._robotQty;i++)
		if (_pos[i].x != (_spiele._robot[i].col()-_col)*SIZE || 
			_pos[i].y != (_spiele._robot[i].row()-_row)*SIZE ||
			_x != _col*SIZE ||
			_y != _row*SIZE)
			return false;
	return true;
}

//mise à jour graphique
//vas positionner le level avec le deplacement
//et repositionner les SDL_Rect du les robots
template < int _LVLW, int _LVLH>
void spieleUI<_LVLW,_LVLH>::update()
{
    //ici on evalu la position par rapport au centre du _transbot
	if (_spiele._transbot.size())
	{
	    //moyenne des positions de tous les bots attachés.
		_col = _row = 0;
		_spiele._transbot.reset();
		while (!_spiele._transbot.end())
		{
			_col+=_spiele._transbot.peek()->col();
			_row+=_spiele._transbot.peek()->row();
			_spiele._transbot.next();
		}
		_col/=_spiele._transbot.size();
		_row/=_spiele._transbot.size();
		//verification par rapport au level
		if (_col < 20)
			_col = 0;
		else if (_col > _LVLW-20)
			_col = _LVLW-40;
		else
			_col = (_col-20);
		if (_row < 13)
			_row = 0;
		else if (_row > _LVLH-13)
			_row = _LVLH-25;
		else
			_row = (_row-13);
	}
	
	if (_w<40)  //ajout de derniere minute, je ne veux que les levels plus grand que l'ecran bougent
	{
	    _col=0;
	}
	if (_h<25)
	{
	    _row=0;
	}
	//si le level n'est pas en place avancer vers la position désirer de un pixel

	    if (_x < _col*SIZE)
		    _x++;
	    else if(_x > _col*SIZE)
		    _x--;
	    if (_y < _row*SIZE)
		    _y++;
	    else if(_y > _row*SIZE)
		    _y--;
    //si un robot n'est pas la position desiré, avance d'un pixel
	for (int i=0;i<_spiele._robotQty;i++)
	{
		if (_pos[i].x < (_spiele._robot[i].col()*SIZE)-_x)
			_pos[i].x++;
		else if (_pos[i].x > (_spiele._robot[i].col()*SIZE)-_x)
			_pos[i].x--;
		if (_pos[i].y < (_spiele._robot[i].row()*SIZE)-_y)
			_pos[i].y++;
		else if (_pos[i].y > (_spiele._robot[i].row()*SIZE)-_y)
			_pos[i].y--;
	}
}

//affichage
//redessine le level
//redessine les bots
template < int _LVLW, int _LVLH>
void spieleUI<_LVLW,_LVLH>::draw(SDL_Surface * ecran, int x, int y)
{
	SDL_Rect tmp,tmp2;  //deux rectangles temporaires
    //tout est en saut de SIZE pixel, voir main.hpp
	//dessiner le level
	tmp.w=SIZE;
	tmp.h=SIZE;
	for (int i=0;i<_w;i++)
		for (int j=0;j<_h;j++)
		{
			tmp.x = i*SIZE - (_x-(_col*SIZE));
			tmp.y = j*SIZE - (_y-(_row*SIZE));
			switch (_spiele._lvl.at(i+_col,j+_row))
			{
			case '#':
				tmp2 = block;
				break;
			case '!':
				tmp2 = casse;
				break;
			case '<':
				tmp2 = tapisG;
				break;
			case '>':
				tmp2 = tapisD;
				break;
			case '@':
				tmp2 = goal;
				break;
			default:
				tmp2 = bg;
				break;
			}
			tmp.x+=x;
			tmp.y+=y;
			SDL_BlitSurface(_spriteSheet, &tmp2, ecran, &tmp);
		}
	//dessiner les robot
	for (int i=0;i<_spiele._robotQty;i++)
	{
	    //robot en liberté .type == 0 , ou robot attaché
		if (_spiele._robot[i].type != '0')
		{
			tmp2 = sprBody;
		}
		else
		{
			tmp2 = sprBot;
			tmp2.x = i*SIZE;
		}
		//petite decoration , yeux et bouche du gros robot
		if (_spiele._transbot.size() < 7 && _spiele._robot[i].type == _spiele._transbot.lastType)
			tmp2 = sprEyes;
		else if (_spiele._transbot.size() > 6)
		{
		    if (_spiele._robot[i].type == _spiele._transbot.eye)
		        tmp2 = sprEyes;
		    else if (_spiele._robot[i].type == _spiele._transbot.teeth)
		        tmp2 = sprTeeth;
		}
		//une foie que l'on a deux rectangle, nous pouvons dessiner
		tmp = _pos[i];
		tmp.x+=x;
		tmp.y+=y;
		SDL_BlitSurface(_spriteSheet, &tmp2, ecran, &tmp);
	}
}

//transmettre le controle au jeux
template <int _LVLW,int _LVLH>
void spieleUI<_LVLW,_LVLH>::control(int k)
{
    if (updated());
	    _spiele.control(k);
}

//activer le jeux pour un cycle
template <int _LVLW,int _LVLH>
bool spieleUI<_LVLW,_LVLH>::process()
{
	return _spiele.process();
}

//tester si la partie est terminé
template <int _LVLW,int _LVLH>
bool spieleUI<_LVLW,_LVLH>::end()
{
	return _spiele.gamewin;
}

//tester si la partie est echoué
template <int _LVLW,int _LVLH>
bool spieleUI<_LVLW,_LVLH>::gameover()
{
	return _spiele.gameover;
}

#endif
