#pragma once
//-----------------------------------------------------
// Name, first name: Hoet, Guntran
// Group: 1DAE3
//-----------------------------------------------------

//-----------------------------------------------------
// Include Files
//-----------------------------------------------------
#include "GameEngine.h"
#include "Level.h"
#include "Sound.h"

//#include "SuperMarioBros.h"
//#include "Fireball.h"
//-----------------------------------------------------
// Mario Class									
//-----------------------------------------------------
class Fireball;
class SuperMarioBros;
class HUD;

class Mario
{
private:
	Mario();				// Constructor
	static Mario* m_MarioPtr;

public:
	virtual ~Mario();		// Destructor
	static Mario* GetSingleton();

	//-------------------------------------------------
	// Methods - Member functions							
	//-------------------------------------------------

	void Tick(double deltaTime);
	void Paint(MATRIX3X2 matView);
	void PaintHitregions(MATRIX3X2 matView);
	void ShootFireball();

	int GetWidth();
	int GetHeight();
	//0 = small
	//1 = big
	//2 = fire
	int GetFormState();
	//0 = Waiting
	//1 = Walking
	//2 = Dying
	//3 = Falling
	//4 = Shrink
	//5 = Grow
	//6 = transform end
	//7 = Godmode
	int GetBehaviourState();
	// true = mario goes right
	// false = mario goes left
	bool GetDirection();

	void Grow();
	void Shrink();

	void SetNoCollisionRects(bool noCollision);
	bool HasNoCollisionRects();

	void Move(DOUBLE2 direction);
	void ReverseVerticalVelocity();
	void DeathJump();
	void KillJump();

	void SetVelocityToZero(bool horizontalVelocity, bool verticalVelocity);
	// if value is .123 the respective axis will not be altered
	void SetPosition(double x, double y);

	void IsHit();
	void SetLife(bool isAlive);
	bool IsAlive();
	void ActivateProtection(int time = 0);
	void ProtectionTick();

	void ActivateStarman(bool withSound);
	bool IsStarman();
	void StarmanTick();
	
	void WarpToSecretArea();
	void WarpToSpawn();
	void WarpToSecretAreaExit();
	void WarpToCheckPoint();
	// 0 = pipe down
	// 1 = pipe right
	// 2 = go in castle
	void StartPipeAnimation(int animNr);

	//0 = small
	//1 = big
	//2 = fire
	void SetFormState(int state);
	//0 = Waiting
	//1 = Walking
	//2 = Dying
	//3 = Falling
	//4 = Shrink
	//5 = Grow
	//6 = transform end
	//7 = Godmode
	void SetBehaviourState(int stateNumber);

	DOUBLE2 GetPosition();

	RECT2 GetHRectOfMario();
	RECT2 GetVRectOfMario();

	void PrintMarioInfo(MATRIX3X2 matView);

	static const int SPEED_VALUE = 120;
	static const int SPEED_MAX = 100;

	static const int FORCE_FRICTION = 400;
	static const int FORCE_GRAVITY = 800;

	static const int JUMP_HEIGHT_NORMAL = 100;
	static const int JUMP_HEIGHT_MAX = 335;
	static const int JUMP_HEIGHT_KILL = 200;

	static const int NR_FIREBALLS = 2;
	static const int RESPAWN_DEPTH_LIMIT = 2000;

	static const int PROTECTION_TIME = 180;

private: 
	enum class FormState : int
	{
		SMALL,
		BIG,
		FIRE
	};

	enum class BehaviourState : int
	{
		WAITING,
		WALKING,
		DYING,
		FALLING,
		SHRINK,
		GROW,
		TRANSFORMATION_END,
		GOD_MODE
	};

	//-------------------------------------------------
	// Own Methods						
	//-------------------------------------------------

	void LoadFromFile();
	void PaintMario();

	void LevelBoundaries();
	void RaycastsVertical();
	void RaycastsHorizontal();

	void ShrinkBigToSmall();
	void ShrinkFireToSmall();

	void GrowSmallToBig();
	void GrowBigToFire();

	void AutoRespawn();
	void CheckDirection();
	void GoDownInPipe();
	void GoRightInPipe();
	void GoInCastle();

	//-------------------------------------------------
	// Datamembers								
	//-------------------------------------------------

	static const int NR_WALKING_CLIPS = 3;
	static const int NR_HOPPING_CLIPS = 3;
	static const int NR_JUMPING_CLIPS = 5;

	static const int STEP_WIDTH = 16;
	static const int STEP_HEIGHT_BIG = 32;
	static const int STEP_HEIGHT_SMALL = 16;
	static const int INTERVAL = 8;				// interval on which the animation step increments

	static const int TRANSFORM_INTERVAL = 10;
	static const int TRANSFORM_TIME = 90;

	static const int STARMAN_TIME = 300;
	static const int PIPE_ANIM_TIME = 90;

	bool m_IsGoingRight, 
		m_CanJump, m_IsAlive, 
		m_NoCollisionRects, 
		m_IsTransforming, 
		m_TransformSmallToBig, m_TransformingBigToFire, m_TransformingBigToSmall, m_TransformingFireToSmall,
		m_TransformSwitch,
		m_CheckpointPassed,
		m_IsStarman,
		m_InPipeAnimationDown,
		m_InPipeAnimationRight,
		m_InCastleGoing;

	int m_MarioWidth, m_SmallMarioHeight, m_BigMarioHeight;
	int m_TickCount, m_AnimationSlowDown, m_DirectionScale;
	int m_TransformTickCount, m_TransformTime, m_ProtectionTimer;
	int m_StarmanTimer, m_StarmanTickCount, m_AnimationLimit, m_PipeAnimTimer;
	double m_DeltaTime;

	DOUBLE2 m_Position, m_Velocity, m_Gravity;
	DOUBLE2 m_RespawnPos;

	Bitmap* m_BmpMarioPtr;
	Bitmap* m_BmpFireballPtr;
	Bitmap* m_BmpExplosionPtr;

	HitRegion* m_HitWorldPtr;

	FormState m_FormState;
	BehaviourState m_BehaviourState;

	Fireball *m_FireballPtrArr[NR_FIREBALLS];

	// -------------------------
	// Disabling default copy constructor and default 
	// assignment operator.
	// -------------------------
	Mario(const Mario& yRef);									
	Mario& operator=(const Mario& yRef);	
};


