/***************************************************************************
 *   Copyright (C) 2004-2005 by                                            *
 *     Paolo Sacconier   <axa1981@tin.it>                                  *
 *     Francesco Tamagni <minchiahead@hacari.org>                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "menu.h"

namespace gillo {

const float Menu::elementCoord[3][4] = {{0.225, 0.44, 0.58, 0.55},
									    {0.317, 0.33, 0.617, 0.44},
									    {0.415, 0.21, 0.81, 0.31}};

Menu::Menu(Video& v, Sound& s, queue<Event>& eq)
: video(v), sound(s), equeue(eq), status(INVISIBLE), selectedElement(0), gameTriggered(false)
{
	for (int i = 0; i < 4; i++)
		selectorCoord[i] = elementCoord[selectedElement][i];
	
	currentCar[0] = selectedCar[0] = 0;
	currentCar[1] = selectedCar[1] = 0;
		
	
	changeStatus(VISIBLE);
}


Menu::~Menu()
{
	printf("Menu(%p): destroyed\n",this);
}


void Menu::loadTextures() {
	// textures for vehicle change menu
	carPicPtr[1][0] = 	new Img(0.148, 0.483, 0.148 + 0.346, 0.483 + 0.367, TEX_MENU_CV_OMNI_2);
	carPicPtr[1][1] = 	new Img(0.148, 0.483, 0.148 + 0.346, 0.483 + 0.367, TEX_MENU_CV_FOUR_2);
	carPicPtr[0][0] = 	new Img(0.531, 0.483, 0.531 + 0.346, 0.483 + 0.367, TEX_MENU_CV_OMNI_1);
	carPicPtr[0][1] = 	new Img(0.531, 0.483, 0.531 + 0.346, 0.483 + 0.367, TEX_MENU_CV_FOUR_1);
	carTextPtr[1][0] = 	new Img(0.226, 0.414, 0.226 + 0.19,  0.414 + 0.04 , TEX_MENU_CV_OMNI_TEXT);
	carTextPtr[1][1] = 	new Img(0.231, 0.414, 0.231 + 0.173, 0.414 + 0.04 , TEX_MENU_CV_FOUR_TEXT);
	carTextPtr[0][0] = 	new Img(0.618, 0.414, 0.618 + 0.19,  0.414 + 0.04 , TEX_MENU_CV_OMNI_TEXT);
	carTextPtr[0][1] = 	new Img(0.625, 0.414, 0.625 + 0.173, 0.414 + 0.04 , TEX_MENU_CV_FOUR_TEXT);
	okPtr[1] = 		new Img(0.180, 0.572, 0.180 + 0.28,  0.572 + 0.21 , TEX_MENU_CV_OK_BUTTON);
	okPtr[0] = 		new Img(0.563, 0.572, 0.563 + 0.28,  0.572 + 0.21 , TEX_MENU_CV_OK_BUTTON);
	leftButtonPtr[1] =	new Img(0.144, 0.402, 0.144 + 0.036, 0.402 + 0.057, TEX_MENU_CV_LEFT_BUTTON);
	rightButtonPtr[1] =	new Img(0.46 , 0.402, 0.46  + 0.036, 0.402 + 0.057, TEX_MENU_CV_RIGHT_BUTTON);
	leftButtonPtr[0] =	new Img(0.527, 0.402, 0.527 + 0.036, 0.402 + 0.057, TEX_MENU_CV_LEFT_BUTTON);
	rightButtonPtr[0] =	new Img(0.844, 0.402, 0.844 + 0.036, 0.402 + 0.057, TEX_MENU_CV_RIGHT_BUTTON);
	cvBackPtr = 		new Img(0.0  , 0.0  , 1.0          , 1.0          , TEX_MENU_CV_BACK);
	
	// textures for main menu
	aImgPtr     = 		new Img(0.0 , 0.0 , 1.0 , 1.0 , TEX_MENU);
	selectorPtr = 		new Img(selectorCoord[0], selectorCoord[1], selectorCoord[2], selectorCoord[3], TEX_MENU_SEL);
}


void Menu::unloadTextures() {
	for (int i = 0; i < numPlayers; i++){
		for (int j = 0; j < numCars; j++){
			delete carPicPtr[i][j];
			delete carTextPtr[i][j];
			carPicPtr[i][j] = NULL;
			carTextPtr[i][j]= NULL;
		}
		delete okPtr[i];
		delete leftButtonPtr[i];
		delete rightButtonPtr[i];
		okPtr[i] = NULL;
		leftButtonPtr[i] = NULL;
		rightButtonPtr[i] = NULL;
	}
	delete cvBackPtr;
	delete aImgPtr;
	delete selectorPtr;
	cvBackPtr = NULL;
	aImgPtr = NULL;
	selectorPtr = NULL;
}

void Menu::update(double dt)
{
	if (status == VISIBLE) {
		for (int i = 0; i < 4; i++)
			selectorCoord[i] += 4*(elementCoord[selectedElement][i] -selectorCoord[i])*dt;
		if (this->selectorPtr)
			this->selectorPtr->setCoords(selectorCoord[0], selectorCoord[1], selectorCoord[2], selectorCoord[3]);
	}
	if (status == CHANGE_VEHICLE) {
		if (ok[0] && ok[1])
			changeStatus(VISIBLE);
	}
}

void Menu::react(SDL_Event *event)
{
	if (status == VISIBLE || status == CHANGE_VEHICLE) {
		switch( event->type ) {
			case SDL_KEYDOWN:
				handleKeyDown(&event->key.keysym);
				break;
			case SDL_KEYUP:
				handleKeyUp(&event->key.keysym);
				break;
			case SDL_QUIT:
				{
					Event ev(Event::APP, Event::QUIT);
					equeue.push(ev);
				}
				break;
			default:
	//			throw Error::Event("Unhandled event");
				break;
		}
	}
}

void Menu::handleKeyDown( SDL_keysym* keysym )
{
	switch( keysym->sym ) {
		case SDLK_ESCAPE: {
			if (status == VISIBLE && gameTriggered) {
				this->sound.play(Sound::MENUSEL);
				Event ev(Event::GAME, Event::RESUME);
				equeue.push(ev);
				changeStatus(INVISIBLE);
			} else if (status == CHANGE_VEHICLE) {
				this->sound.play(Sound::MENUSEL);
				changeStatus(VISIBLE);
				selectedCar[0] = currentCar[0];
				selectedCar[1] = currentCar[1];
			}
			} break;
		case SDLK_RETURN: {
			if (status == VISIBLE) {
				this->sound.play(Sound::MENUSEL);
				if (selectedElement == 0){
					Event ev(Event::GAME, Event::START);
					equeue.push(ev);
					changeStatus(INVISIBLE);
					this->gameTriggered = false;
				} else if (selectedElement == 1) {
					Event ev(Event::GAME, Event::START_TRAINING);
					equeue.push(ev);
					changeStatus(INVISIBLE);
					this->gameTriggered = false;
				} else if (selectedElement == 2) {
					changeStatus(CHANGE_VEHICLE);
				}
			} 
			} break;
		case SDLK_m:
			if (status == CHANGE_VEHICLE) {
				this->sound.play(Sound::MENUSEL);
				if (!ok[0]) {
					ok[0] = true;
					video.overlay.add(okPtr[0]);
					currentCar[0] = selectedCar[0];
					switch (currentCar[0]) {
						case CAR_OMNICAR: {
							Event ev(Event::GAME, Event::CV_P1_OMNICAR);
							equeue.push(ev);
							break;
							}
						case CAR_FOURCAR: {
							Event ev(Event::GAME, Event::CV_P1_FOURCAR);
							equeue.push(ev);
							break;
							}
					}
				} else {
					ok[0] = false;
					video.overlay.rem(okPtr[0]);
				}
			}
			break;
		case SDLK_z:
			if (status == CHANGE_VEHICLE) {
				this->sound.play(Sound::MENUSEL);
				if(!ok[1]){
					ok[1] = true;
					video.overlay.add(okPtr[1]);
					currentCar[1] = selectedCar[1];
					switch (currentCar[1]) {
						case CAR_OMNICAR: {
							Event ev(Event::GAME, Event::CV_P2_OMNICAR);
							equeue.push(ev);
							break;
							}
						case CAR_FOURCAR:{
							Event ev(Event::GAME, Event::CV_P2_FOURCAR);
							equeue.push(ev);
							break;
							}
					}
				} else {
					ok[1] = false;
					video.overlay.rem(okPtr[1]);
				}
			}
			break;
		case SDLK_LEFT:
			if (status == CHANGE_VEHICLE) {
				if(!ok[0])
					this->showCar(0, (selectedCar[0] == 0) ? 0 : selectedCar[0]-1);
				this->sound.play(Sound::MENUSEL);
			}
			break;
		case SDLK_RIGHT:
			if (status == CHANGE_VEHICLE) {
				if(!ok[0])
					this->showCar(0, (selectedCar[0] == numCars-1) ? selectedCar[0] : selectedCar[0]+1);
				this->sound.play(Sound::MENUSEL);
			}
			break;
		case SDLK_x:
			if (status == CHANGE_VEHICLE) {
				if(!ok[1])
					this->showCar(1, (selectedCar[1] == 0) ? 0 : selectedCar[1]-1);
				this->sound.play(Sound::MENUSEL);
			}
			break;
		case SDLK_v:
			if (status == CHANGE_VEHICLE) {
				if(!ok[1])
					this->showCar(1, (selectedCar[1] == numCars-1) ? selectedCar[1] : selectedCar[1]+1);
				this->sound.play(Sound::MENUSEL);
			}
			break;
		case SDLK_UP: {
			if (status == VISIBLE) {
				selectedElement = (selectedElement == 0) ? 0 : selectedElement-1;
				this->sound.play(Sound::MENUSEL);
			}
			} break;
		case SDLK_DOWN: {
			if (status == VISIBLE) {
				selectedElement = (selectedElement == numElements-1) ? selectedElement : selectedElement+1;
				this->sound.play(Sound::MENUSEL);
			} 
			} break;
		default:
			break;    
	}
}

void Menu::handleKeyUp( SDL_keysym* keysym ) {
    switch( keysym->sym ) {
		default:
			break;
	}
}

void Menu::react(const Event::Type et)
{
	switch (et) {
		case Event::SHOW:
			this->gameTriggered = true;
			this->changeStatus(VISIBLE);
			break;
		case Event::HIDE: //@fixme remove this
			this->changeStatus(INVISIBLE);
			break;
		default:
			break;
	}
}

void Menu::showCar(int playerId, int desiredCar) {
// 	if (desiredCar == selectedCar[playerId]) return;
	
	video.overlay.add(rightButtonPtr[playerId]);
	video.overlay.add(leftButtonPtr[playerId]);
	
	if (desiredCar == numCars-1)
		video.overlay.rem(rightButtonPtr[playerId]);
	if ( desiredCar == 0)
		video.overlay.rem(leftButtonPtr[playerId]);
		
	
	video.overlay.rem(carPicPtr[playerId][selectedCar[playerId]]);
	video.overlay.rem(carTextPtr[playerId][selectedCar[playerId]]);
	video.overlay.add(carPicPtr[playerId][desiredCar]);
	video.overlay.add(carTextPtr[playerId][desiredCar]);
	
	selectedCar[playerId] = desiredCar;
}

bool Menu::changeStatus(Status s)
{
	if ((status == VISIBLE) && ((s == INVISIBLE) || (s == CHANGE_VEHICLE))) {
		status = s;
		video.overlay.rem(aImgPtr);
		video.overlay.rem(selectorPtr);
		if (s == CHANGE_VEHICLE) {
			ok[0] = ok[1] = 0;
			video.overlay.add(cvBackPtr);
			showCar(0, selectedCar[0]);
			showCar(1, selectedCar[1]);
		} else {
			unloadTextures();
		}
	} else if (((status == INVISIBLE) || (status == CHANGE_VEHICLE)) && (s == VISIBLE)) {
		if (status == CHANGE_VEHICLE) {
			usleep(100000);
			video.overlay.rem(carPicPtr[0][selectedCar[0]]);
			video.overlay.rem(carPicPtr[1][selectedCar[1]]);
			video.overlay.rem(carTextPtr[0][selectedCar[0]]);
			video.overlay.rem(carTextPtr[1][selectedCar[1]]);
			video.overlay.rem(leftButtonPtr[0]);
			video.overlay.rem(leftButtonPtr[1]);
			video.overlay.rem(rightButtonPtr[0]);
			video.overlay.rem(rightButtonPtr[1]);
			video.overlay.rem(okPtr[0]);
			video.overlay.rem(okPtr[1]);
			video.overlay.rem(cvBackPtr);
			
		} else {
			sound.music(Sound::MENU);
			loadTextures();
		}
		status = s;
		video.overlay.add(aImgPtr);
		video.overlay.add(selectorPtr);
		
	} else {
		//@fixme throw something
	}
}

};
