// gameballworld.h  A side-scroller game.
//
//////////////////////////////////////////////////////////////////////

#ifndef GAMEBALLWORLD_H
#define GAMEBALLWORLD_H

#include "game.h"
#include "critterarmed.h"
#include "critterwall.h"

//==============Critters for the cGameBallworld: Player, Ball, Treasure ================

class cCritterBallworldPlayer : public cCritterArmedPlayer 
{
DECLARE_SERIAL(cCritterBallworldPlayer)
private:
	Real _lasthit;  // Age when last hit.

	

public:
	cCritterBallworldPlayer(cGame *pownergame = NULL);
	BOOL collide(cCritter *pcritter);
	
	void setLasthit(Real time){_lasthit = time;}
	Real lasthit(){return _lasthit;}
	
	int livesLeft;
};

class cCritterBallProp : public cCritterArmedRobot
{
DECLARE_SERIAL(cCritterBallProp)
private:
	bool dead;
	
	Real left_range;
	Real right_range;
	bool isFlying;

	int pic;

	int id;

public:
	cCritterBallProp(cGame *pownergame = NULL);
	void update(CPopView *pactiveview, Real dt); // do a delete_me if you hit the left end
	void die(); //Overload to give score to the player when it jumps on it.

	// functions we've added
	bool isDead() { return dead; }
	cCritterBallProp(cGame *pownergame, Real _left_range, Real _right_range, bool _isFlying, Real init_velocity, int _pic, int id);
};

class cCritterTreasure : public cCritter
{ //Treasures to pickup, give health or score.
DECLARE_SERIAL(cCritterTreasure)
private:
	int health;
	int score;
public:
	int id;
	cCritterTreasure(cGame *pownergame = NULL):cCritter(pownergame){}
	cCritterTreasure(cGame *pownergame, Real xPosition, Real yPosition, int _health, int _score, int id);
	void die();
	virtual BOOL collide(cCritter *pcritter); //Checks if pcritter inside.
	int cCritterTreasure::collidesWith(cCritter *pothercritter); /* Only collide
		with cCritterBallworldPlayer. */
};


//======================cGameBallworld==========================

// forward declaration
// we "love" POP!
class cCritterBallWall;

class cGameBallworld : public cGame
{
DECLARE_SERIAL(cGameBallworld);
public:
	static Real WALLTHICKNESS;
	static Real TREASURERADIUS;
	static Real LEVELTIMER;

	bool*	           _theseEnemyIDs;
	bool*              _theseGoodyIDs;

private:
	cCritterTreasure* _ptreasure;
	cCritterBallProp** _theseEnemies;
	cCritterBallWall** _theseWalls;
	cCritterTreasure** _theseGoodies;

	int _cur_level;
	int _numLevels;

	bool gameStarted;
	int _last_level;

	


	struct _enemy
	{
		_enemy()
		{
			_enemy(0, 0, 0, 0, false, 0, IDB_ITR);
		}

		_enemy(Real x, Real y, Real lrange, Real rrange, bool isFlying, Real initVel, int pic)
			: x(x),
			  y(y),
			  lrange(lrange),
			  rrange(rrange),
			  isFlying(isFlying),
			  initVel(initVel),
			  pic(pic)
		{ }

		Real x;
		Real y;

		Real lrange;
		Real rrange;
		bool isFlying;
		Real initVel;

		int pic;

		cVector2 getVector()
		{
			return cVector2(x, y);
		}
	};

	struct _wall
	{
		_wall()
		{
			_wall(0, 0, 0, 0);
		}

		_wall(Real ux, Real uy, Real lx, Real ly)
			: ux(ux),
			  uy(uy),
			  lx(lx),
			  ly(ly)
		{ }

		Real ux;
		Real uy;
		Real lx;
		Real ly;

		cVector2 getUpperVector()
		{
			return cVector2(ux, uy);
		}

		cVector2 getLowerVector()
		{
			return cVector2(lx, ly);
		}
	};

	struct _goodie
	{
		Real _x;
		Real _y;
		int  _health;
		int  _score;

		_goodie()
		{
			_goodie(0, 0, 0, 0);
		}

		_goodie(Real x, Real y, int health, int score)
			: _x(x), _y(y), _health(health), _score(score)
		{ }
	};



	struct _level
	{
		int _lastEnemy;
		int _lastWall;
		int _lastGoodie;

		int _scoreBonus;

		int _numEnemies;
		int _numWalls;
		int _numGoodies;

		int _timeLimit;
		int _bgbmp;

		_enemy*  _enemies;
		_wall*   _walls;
		_goodie* _goodies;

		_level()
			: _lastEnemy(0),
			  _lastWall(0),
			  _lastGoodie(0)
		{
			init(0, 0, 0, 0, 0, 0);
		}

		void init(int numEnemies, int numWalls, int numGoodies, int scoreBonus, int timeLimit, int bgbmp)
		{
			_numEnemies = numEnemies;
			_numWalls   = numWalls;
			_numGoodies = numGoodies;
			_scoreBonus = scoreBonus;
			_timeLimit  = timeLimit;
			_bgbmp	    = bgbmp;

			if (numEnemies > 0)
				_enemies = new _enemy[numEnemies];
			else
				_enemies = NULL;

			if (numWalls > 0)
				_walls   = new _wall [numWalls];
			else
				_walls   = NULL;

			if (numGoodies > 0)
				_goodies = new _goodie[numGoodies];
			else
				_goodies = NULL;
		}

		_level(int numEnemies, int numWalls, int numGoodies, int scoreBonus, int timeLimit, int bgbmp) 
			: _lastEnemy(0),
			  _lastWall(0),
			  _lastGoodie(0)
		{
			init(numEnemies, numWalls, numGoodies, scoreBonus, timeLimit, bgbmp);
		}

		~_level()
		{
			delete [] _enemies;
			delete [] _walls;
			delete [] _goodies;
		}

		void addEnemy(Real x, Real y, Real lrange, Real rrange, bool isFlying, Real iVel, int pic)
		{
			if (_lastEnemy >= _numEnemies)
				return;

			_enemies[_lastEnemy++] = _enemy(x, y, lrange, rrange, isFlying, iVel, pic);
		}

		void addWall(Real ux, Real uy, Real lx, Real ly)
		{
			_walls  [_lastWall++ ] = _wall(ux, uy, lx, ly);
		}

		void addGoodie(Real x, Real y, int shealth, int sscore)
		{
			_goodies[_lastGoodie++]= _goodie(x, y, shealth, sscore);

		}
	};

	_level* _levels;

public:
	cGameBallworld();
	virtual int worldShape(){return cGame::SHAPE_XSCROLLER;} 
		/* Need this to signal the cCritterViewer to not wobble up and down when
		 _trackplayer is on. Overrides the default worldShape of cGame::SHAPE_RECT.*/
	virtual void seedCritters();

	virtual void gotoNextLevel(cCritter*);

	virtual void initializeView(CPopView *pview);
	virtual void initializeViewpoint(cCritterViewer *pviewer); /* Move over to be above the
		lower left corner where the player is.  In 3D, use a low viewpoint low looking up. */
	virtual void adjustGameParameters();
	virtual CString statusMessage();
	virtual void Serialize(CArchive& ar);
};

//======Add walls to wonderful Ballworld======
class cCritterBallWall : public cCritterWall
{
DECLARE_SERIAL(cCritterBallWall);
public:
	cCritterBallWall(cGame *pownergame = NULL):cCritterWall(pownergame){}
		//Don't actually use this one.
	cCritterBallWall(const cVector &enda, const cVector &endb, 
		Real thickness = cGameBallworld::WALLTHICKNESS, cGame *pownergame= NULL);
};

#endif //GAMEBALLWORLD_H