#ifndef _ITEM_H_
#define _ITEM_H_

#include <list>
#include <string>

//These work because I am not using actual objects in here; only pointers
class Room;
struct Exit;

enum ItemType
{
	eTake,
	eHold,
	eCheck,
	eUse,
	ePush,
};

class Item
{
protected:
	const std::string mName;
	std::string mDescription;
	const std::string mTakeDescription;
	const ItemType mType;
	bool mScoreChecked; //For giving score the first time you check an item
	bool mScoreOther; //This is for adding score to the different kinds of items, like using it in the right place, taking an item, etc.

public:
	Item(ItemType aType, std::string aName, std::string aDescription, std::string aTakeDescription);
	virtual ~Item() {}
	virtual std::string GetDescription();
	void TakeItemDescriptions();
	std::string GetName() const { return mName; }
	std::string GetTakeDescription() const {return mTakeDescription; }
	ItemType GetType() const { return mType; }

	static int sItemCount;
	static int sItemTakeCount;
	static int sItemHoldUseCount;
};



class ItemTakable : public Item
{
public:
	ItemTakable(std::string aName, std::string aDescription, std::string aTakeDescription);
};

class ItemCheckable : public Item
{
public:
	ItemCheckable(std::string aName, std::string aDescription, std::string aTakeDescription);
};

class ItemEndGame : public ItemCheckable
{
public:
	ItemEndGame(std::string aName, std::string aDescription, std::string aTakeDescription);

	std::string GetDescription();
};

class ItemPushable : public Item
{
public:
	ItemPushable(std::string aName, std::string aDescription, std::string aTakeDescription);
};

class ItemHolder : public Item
{
	bool mCorrectItemHeld;
	std::string mCorrectItemDescription;
	std::string mDescriptionBase;
	Item* mHeld;
	Item* mItemLooking;

public:
	ItemHolder(std::string aName, std::string aDescription, std::string aTakeDescription, std::string aCorrectItemDescription);

	void AddItemLooking(Item* aItemLooking);
	bool AddItem(Item* aItem);
	void RemoveItem();
	void CheckHoldingItem();

	bool HoldingCorrectItem() const { return mCorrectItemHeld; }
	Item* GetHeld() const { return mHeld; }
};

//	>>ItemUse<<
class ItemUse : public Item
{
protected:
	bool mUsed; //Checking if the item found the mItemLooking
	bool mDestroy;
	Item* mItemLooking;
	std::string mDescriptionBase;
	std::string mCorrectItemDescription;
	std::string mIncorrectItemDescription;

	virtual void Use() = 0;

public:
	ItemUse(bool aDestroy, std::string aName, std::string aDescription, std::string aTakeDescription, std::string aCorrectItemDescription, std::string aIncorrectItemDescription);
	
	void AddItemLooking(Item* aItemLooking);
	void CheckUse(Item* aUsingItem);
	bool CheckDestroy() const { return mDestroy; }
	bool CheckUsed() const { return mUsed; }
};

class UseChest : public ItemUse
{
	std::list <Item*> mItems;
	void Use();
public:
	UseChest(bool aDestroy, std::string aName, std::string aDescription, std::string aTakeDescription, std::string aCorrectItemDescription, std::string aIncorrectItemDescription);
	~UseChest();
	void AddItem(Item* aItem);
};


class UseLockedDoor : public ItemUse
{
	Exit* mExit;
	Room* mExitsRoom;
	void Use();
public:
	UseLockedDoor(bool aDestroy, std::string aName, std::string aDescription, std::string aTakeDescription, std::string aCorrectItemDescription, std::string aIncorrectItemDescription);
	~UseLockedDoor();
	void AddExit(Exit* aExit, Room* aExitInRoom);
};

//	>>ItemUse<<

#endif //Close _ITEM_H_