#ifndef COMMAND_H
#define COMMAND_H

#include <string>
#include "SDL_mixer.h"
#include "Sprite.h"

class Object;
class Person;
class Player;
class List;

class Command
{
public:
	virtual void execute()=0;
	virtual std::string getString()=0;
	static Command *loadCommand(List *command);

};

class JumpCommand : public Command
{
public:
	JumpCommand(Person* person, xDirection xDir);
	JumpCommand(List *command);
	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
//	Person* _person;
	std::string _person;
	xDirection _xDir;

	static const std::string _id;
};

class JumpResetCommand : public Command
{
public:
	JumpResetCommand(Person* person);
	JumpResetCommand(List *command);
	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	//Person* _person;
	std::string _person;

	static const std::string _id;
};

class CrouchCommand : public Command
{
public:
	CrouchCommand(Person* person, bool crouch = true);
	CrouchCommand(List *command);
	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person* _person;
	bool _crouch;

	static const std::string _id;
};

class MoveCommand: public Command
{
public:
	MoveCommand(Person *person, xDirection xDir);
	MoveCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	//Person * _person;
	std::string _person;
	xDirection _xDir;

	static const std::string _id;
};

class TurnCommand: public Command
{
public:
	TurnCommand(Person *person, xDirection xDir);
	TurnCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person * _person;
	xDirection _xDir;

	static const std::string _id;
};

class PlayMusicCommand: public Command
{
public:
	PlayMusicCommand( std::string filename );
	PlayMusicCommand( List* command );
	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	Mix_Music* _music;
	std::string _filename;

	static const std::string _id;
};

class PlaySoundCommand: public Command
{
public:
	PlaySoundCommand( std::string filename );
	PlaySoundCommand( List* command );
	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	std::string _filename;

	static const std::string _id;
};

class FollowPlayerCommand: public Command
{
public:
	FollowPlayerCommand(Person *person);
	FollowPlayerCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person * _person;

	static const std::string _id;
};

class FollowPlayerInRangeCommand: public Command
{
public:
	FollowPlayerInRangeCommand(Person *person, int range);
	FollowPlayerInRangeCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person * _person;
	int _range;

	static const std::string _id;
};

class RunFromPlayerInRangeCommand: public Command
{
public:
	RunFromPlayerInRangeCommand(Person *person, int range);
	RunFromPlayerInRangeCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person * _person;
	int _range;

	static const std::string _id;
};

class ShootInRangeCommand: public Command
{
public:
	ShootInRangeCommand(Person *person, int range);
	ShootInRangeCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	Person * _person;
	int _shootRange;
	static const std::string _id;
};

class ShootCommand: public Command
{
public:
	ShootCommand(Person *person);
	ShootCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	//Person * _person;
	std::string _person;
	static const std::string _id;
};

class SecondaryShootCommand: public Command
{
public:
	SecondaryShootCommand(Player *player);
	SecondaryShootCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	Player * _player;
	static const std::string _id;
};

class CutSceneTextCommand : public Command
{
public:
	CutSceneTextCommand(std::string text);
	CutSceneTextCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() { return _id; }
private:
	std::string _text;
	static const std::string _id;
};

class SetCameraCommand : public Command
{
public:
	SetCameraCommand(Object *object);
	SetCameraCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Object *_object;
	static const std::string _id;
};

class SetControlCommand : public Command
{
public:
	SetControlCommand(Object *object);
	SetControlCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Object *_object;
	static const std::string _id;
};

class PlayScriptCommand : public Command
{
public:
	PlayScriptCommand(std::string filename);
	PlayScriptCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _filename;
	static const std::string _id;
};

class SetCutSceneCommand : public Command
{
public:
	SetCutSceneCommand(bool cutScene);
	SetCutSceneCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	bool _cutScene;
	static const std::string _id;
};

class AimCommand: public Command
{
public:
	AimCommand(Person *person, yDirection yDir);
	AimCommand(Person *person, Object *target = NULL);
	AimCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	//Person* _person;
	std::string _person;
	yDirection _yDir;
	xDirection _xDir;

	Object* _target;

	static const std::string _id;
};

class AddHealthCommand: public Command
{
public:
	AddHealthCommand(Person *person, int dHealth);
	AddHealthCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Person* _person;
	int _dHealth;

	static const std::string _id;
};

class Door;
class SetDoorLockCommand: public Command
{
public:
	SetDoorLockCommand(Door *door, bool locked);
	SetDoorLockCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	Door* _door;
	bool _locked;

	static const std::string _id;
};

class AddScoreCommand: public Command
{
public:
	AddScoreCommand(int score);
	AddScoreCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	int _score;

	static const std::string _id;
};

class AddWeaponCommand: public Command
{
public:
	AddWeaponCommand(Player *player, std::string filename);
	AddWeaponCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _filename;
	Player *_player;

	static const std::string _id;
};

class EndLevelCommand: public Command
{
public:
	EndLevelCommand();
	EndLevelCommand(List * list);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:

	static const std::string _id;

};

class StopPersonCommand: public Command
{
public:
	StopPersonCommand(Person *person);
	StopPersonCommand(List * list);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	//Person *_person;
	std::string _person;

	static const std::string _id;
};

class SaveCommand: public Command
{
public:
	SaveCommand() {;}
	SaveCommand(List *list) {;}

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	static const std::string _id;
};

class RestoreCommand: public Command
{
public:
	RestoreCommand() {;}
	RestoreCommand(List *list) {;}

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	static const std::string _id;
};

class SetPositionCommand: public Command
{
public:
	SetPositionCommand(Object *object, int xPos, int yPos);
	SetPositionCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	//Object* _object;
	std::string _object;
	int _xPos;
	int _yPos;

	static const std::string _id;
};

class KillCommand: public Command
{
public:
	KillCommand(Person *person);
	KillCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _person;

	static const std::string _id;
};

class LiveCommand: public Command
{
public:
	LiveCommand(Person *person);
	LiveCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _person;

	static const std::string _id;
};

class CutScene;

class ActivateCutSceneCommand: public Command
{
public:
	ActivateCutSceneCommand(CutScene *cutScene);
	ActivateCutSceneCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _cutScene;

	static const std::string _id;
};

class Enemy;
class ActivateEnemyCommand: public Command
{
public:
	ActivateEnemyCommand(Enemy *enemy);
	ActivateEnemyCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _enemy;

	static const std::string _id;
};

class InvincibleCommand: public Command
{
public:
	InvincibleCommand(Person *person, bool inv);
	InvincibleCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	std::string _person;
	bool _inv;

	static const std::string _id;
};

class FlushCommand: public Command
{
public:
	FlushCommand();
	FlushCommand(List *command);

	void execute();
	std::string getString();
	static std::string id() {return _id;}
private:
	static const std::string _id;
};

#endif