#pragma once

#include "GameCore.h"
#include "SpriteStamp.h"
#include "CharacterManager.h"
#include "AStarModified.h"
#include "Node.h"
#include <vector>
#include <stack>

using namespace std;

#define CHARACTER_HEAD_WIDTH 128
#define CHARACTER_HEAD_HEIGHT 128

typedef struct SpriteState {
	int x, y;
	int numFrames;
	RECT* boundingBox;
	int width, height;
    int state;
} SpriteState;

class CharacterManager;
class Character{
public:
    Character( CharacterManager* characterManager, CollisionManager* collisionManager, TextManager* textManager, DialogueManager* dialogueManager, int tileX, int tileY, int dialogue );
	Character( CharacterManager* characterManager, CollisionManager* collisionManager, TextManager* textManager, DialogueManager* dialogueManager, int tileX, int tileY, int trigger, int dialogue );
	~Character();

    enum LOCATION { TOWN, WORLD, BOSS };
	enum TYPE { MAIN, ENEMY, TOWNPERSON, PROJECTILE, WORLDPERSON };
	enum STATE{ WALKING, DEAD, ATTACK, ATTACK_READY, CREATION, DYING, IDLE, ATTACKED, MAGIC, CASTING};
    enum SPEED { NONE, NORMAL, HALF, THIRD, FOURTH, FIFTH, TENTH, TWENTIETH, HUNDREDTH};
	//enum STATE{ IDLE, WALK, WALK_SWORD, SWORD_OUT, ATTACK, MAGIC, DEAD };

	// virtual functions to provide an interface for characters
	virtual bool move( GameCore::DIRECTION aDirection );
	virtual bool move( GameCore::DIRECTION aDirection, GameCore::DIRECTION clipDirection );
	virtual HRESULT tick();
	// get private attributes
	virtual SpriteStamp* getCharacterSpriteStamp();
    virtual SpriteStamp* getCharacterHeadSpriteStamp();
	virtual int getX();
	virtual int getY();
	virtual void setX( int x );
	virtual void setY( int y );
	virtual TILE* getTile();
	virtual void setHeadTextureId( int headTextureId );
	// set clipping rectangle
	virtual void setClip( GameCore::DIRECTION direction );
	virtual void collide( Character* moveChar ) = 0;

	virtual RECT* getBoundingBox();
	virtual void setWalking( bool walk );
    virtual bool getWalking();
    virtual void setDoneCasting(bool done);
    virtual bool getDoneCasting();
    virtual bool getIsAttacking();
    virtual void setIsAttacking(bool attacking);
    virtual bool getIsAttackReady();
    virtual void setIsAttackReady(bool attacking);

	virtual TYPE getType() = 0;
    // push pop top character state
	virtual Character::STATE getState();
	virtual void pushState( STATE newState );
    virtual void popState();
    // get set hp
	virtual int  getHP();
    virtual int getHP_MAX();
	virtual void setHP( int newHP );
    // get set mp
	virtual int  getMP();
    virtual int getMP_MAX();
	virtual void setMP( int newMP );

    virtual int getTrigger();

	virtual GameCore::DIRECTION getFacing();
	virtual void setFacing( GameCore::DIRECTION aDirection );
    virtual void setAttackedFrom( GameCore::DIRECTION aDirection );

    // get a path to destination
	virtual void getPathTo(POINT* destination);

    // getter setter current sprite state
    virtual SpriteState* getCurrentSpriteState();
    virtual void getCurrentSpriteState(SpriteState* spriteState);

    virtual int getStrength();
    virtual void addExperience(int experience);
    virtual int getExperience();

    virtual void setAttacker(Character* attacker);
    virtual void setAttackee(Character* attacker);

    virtual void faceMainCharacter();

	virtual void setLocation( Character::LOCATION _location );
	virtual LOCATION getLocation();

protected:
	virtual void initCharacter(CharacterManager* newCharacterManager, CollisionManager* newCollisionManager, TextManager* newText, DialogueManager* newDialogue, int tileX, int tileY, int trigger, int dialogue );
	virtual void setTextureId( int textureId, int tileX, int tileY, int fullX, int fullY, RECT* boundingBox );
	virtual void setPosition( int tileX, int tileY, RECT* boundingBox );
    // add get set characters sprite
    virtual void addSpriteState( int x, int y, int numFrames, RECT* boundingBox, int width, int height, Character::STATE state );
    virtual SpriteState* getSpriteState( Character::STATE state );
	virtual void setSpriteState( Character::STATE state );
    // move to next frame of animation
    virtual void animateSprite(Character::SPEED slowDown);
    virtual void takeDamage();
    // different actions the character has
	virtual void creation() = 0;
	virtual void idle() = 0;
	virtual void walking() = 0;
	virtual void dying() = 0;
	virtual void attacked() = 0;
	virtual void attack() = 0;
	virtual void attackReady() = 0;
	virtual void dead() = 0;
    virtual void magic() = 0;
    virtual void casting() = 0;

	// moves character closer to final destination if character has a defined path
	virtual void moveToNextPointInPath();
			
	SpriteStamp* characterSprite; // chracter sprite
    SpriteStamp* characterHeadSprite; // close up of chracter head sprite
	RECT* clippingRect; // clipping rectangle
	CollisionManager* collisionManager; // collision manager
	TextManager* textManager;
	DialogueManager* dialogueManager;
	CharacterManager* characterManager;

	bool isWalking;
    bool isCasting;
    bool isDoneCasting;
    bool isAttacking;
    bool isAttackReady;

	stack<STATE>         stateStack;
	vector<SpriteState*> spriteStates;
    SpriteState*         currentSpriteState;

	int HP;
	int HP_MAX;
    int MP;
    int MP_MAX;
    int strength;
    int experience;

    int expEarnedForKilling;

    int triggeredBy;

	vector<POINT*>* path;

	GameCore::DIRECTION facing;
    GameCore::DIRECTION attackedFrom;
    Character* attacker;
    Character* attackee;
	int yOffset;

	int alpha;
	GameCore::DIRECTION dirAttackedFrom;
	int toMove;
    // count number of ticks - used to slow down animation
    int spriteAnimateCount;
    // animation adjustment positions
    int nextX;
    int nextY;
    bool pushOrPop;

    int ticksPassed;
    int animationTickCount;

	int dialogue;

	TILE* tile;

    AStarModified aStar;

	Character::LOCATION location;
};

