/***************************************************************************
 *   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.             *
 ***************************************************************************/

#ifndef GILLOGAME_H
#define GILLOGAME_H

#include "main.h"

#include "video.h"
#include "sound.h"

#include "simpleball.h"
#include "field.h"
#include "goal.h"
#include "goalkeeper.h"
#include "car.h"
#include "omnicar.h"
#include "cube.h"
#include "pwrup.h"

#include "cameraball.h"
#include "cameratrack.h"

#include "context.h"
#include "event.h"
#include "player.h"

namespace gillo {

/**
A game, that contains objects and players.

@author $AUTHOR$
*/
class Game{
	enum Status {
		PAUSED,
		SELFPAUSED,
		RUNNING,
		TRAINING,
		FINISHED
	};
	
	static const float possessionBarLength;
	static const float maxScoreBarLength;
	static const float maxTimerBarLength;
	static const float maxMagnetIntensity;
	static const float splashCoordSet[][4];
	static const float scoreEpsilon;
	static const float possessionEpsilon;
	
	int contactcount;
	
	Context	context;
	vector<Entity*> entities;
	vector<Entity*> tempEntities;
	vector<Entity*> removedEntities;
	vector<Entity*> magneticEntities;
	Goal&		goal;
	SimpleBall&	ball;
	Goalkeeper&	goalkeeper;
	Player	p1;
	Player	p2;
	
	int		frameCount;
	float	topScore;
	float	score;
	float	ballScore;
	float	time;
	float	gameDuration;
	float	goalSplashDuration;
	float randomTimeInterval;
	bool	rotatingGravity;
	bool	goalStatus;
	bool	powerShoot;
	Img*	timerBarPtr;
	Img*	possessionCursorPtr;
	Img*	scoreBarRedPtr;
	Img*	scoreBarBluePtr;
	Img* 	mainOverlayPtr;
	Img*	endSplash;
	Img	goalRedSplash;
	Img	goalBlueSplash;
	Img	tieGoalSplash;
	Img		attractionStautsP1;
	Img		attractionStautsP2;
	Viewport	mainView;
	Viewport	playerTwoView;
	Viewport	playerOneView;
	
	Video&	video;
	Sound&	sound;	
	
	queue<Event>& equeue;
	Status	status;
	Status  previousStatus;
	dContact contacts[ODE_MAX_CONTACTS];
	dJointGroupID contactgroup;    
	
	
	Entity&	addEntity		(Entity* e);
	Entity& addEntityAtRandomPos	(Entity* e, float duration);
	bool	removeEntity	(Entity* e);
	void 	removeEntitiesOfType(Entity::Type et);
	bool	removeMagneticEntity	(Entity* e);
	dContact* collide(Entity* e1, Entity* e2, dGeomID o1, dGeomID o2, dContact* c);
	void handleKeyDown( SDL_keysym* keysym );
	void handleKeyUp  ( SDL_keysym* keysym );

	void startNew();
	inline void updateScore(float dt);
	inline void updatePossession(float dt);
	inline void updatePlayers(float dt);
	void updateTimer(float dt);
	void updateScoreBarHeight(Rect* r, float h, float dt);
	void end();
	
	friend void collide_callback (void *data, dGeomID o1, dGeomID o2);

public:
	Game(Video& v, Sound& s, queue<Event>& eq);
	~Game();
	
	void update(float dt);
	void react(SDL_Event *event);
	void react(const Event::Type et);
	bool changeStatus(Status s);
	
	
	inline Context& getContext() { return context; }
	
};

};

#endif
