#include "Item.h"
#include <string>
#include "Main.h"

int Item::sItemCount = 0;
int Item::sItemTakeCount = 0;
int Item::sItemHoldUseCount = 0;


Item::Item(ItemType aType, std::string aName, std::string aDescription, std::string aTakeDescription) : 
			mName(aName)
			,mDescription(aDescription)
			,mTakeDescription(aTakeDescription)
			,mType(aType)
			,mScoreChecked(0)
			,mScoreOther(0)
{ ++sItemCount; }

void Item::TakeItemDescriptions()
{
	Main::Get()->mOut.Text("You aquired the " + mName + "!");
	Main::Get()->mOut.EndLines(1);
	Main::Get()->mOut.Text(mTakeDescription);

	//Add Score
	if (!mScoreOther && mType == eTake)
	{
		mScoreOther = true;
		Main::Get()->mOut.EndLines(1);
		Main::Get()->AddScore(sScoreTakeItem);
	}

}

std::string Item::GetDescription()
{
	if (!mScoreChecked)
	{
		mScoreChecked = true;
		Main::Get()->AddScore(sScoreCheckItem);
	}

	return mDescription;		
}


ItemTakable::ItemTakable(std::string aName, std::string aDescription, std::string aTakeDescription) : 
			Item(eTake, aName, aDescription, aTakeDescription)
{ ++sItemTakeCount; }


ItemCheckable::ItemCheckable(std::string aName, std::string aDescription, std::string aTakeDescription) : 
			Item(eCheck, aName, aDescription, aTakeDescription)
{}

ItemEndGame::ItemEndGame(std::string aName, std::string aDescription, std::string aTakeDescription) :
			ItemCheckable(aName, aDescription, aTakeDescription)
{}

string ItemEndGame::GetDescription()
{
	Main::Get()->ShowEndScene();

	return "";
}

ItemPushable::ItemPushable(std::string aName, std::string aDescription, std::string aTakeDescription) : 
			Item(ePush, aName, aDescription, aTakeDescription)
{}


ItemHolder::ItemHolder(std::string aName, std::string aDescription, std::string aTakeDescription, std::string aCorrectItemDescription) : 
			Item(eHold, aName, aDescription, aTakeDescription)
			,mDescriptionBase(aDescription)
			,mCorrectItemDescription(aCorrectItemDescription)
			,mHeld(0)
			,mItemLooking(0)
			,mCorrectItemHeld(0)
{ ++sItemHoldUseCount; }

void ItemHolder::AddItemLooking(Item* aItemLooking)
{
	if (!mItemLooking)
		mItemLooking = aItemLooking;

	//Sets its description
	CheckHoldingItem();
}

bool ItemHolder::AddItem(Item* aItem)
{
	bool result = false;

	if (!mHeld)
	{
		mHeld = aItem;
		result = true;
	}
	else
	{
		Main::Get()->mOut.EndLines(1);
		Main::Get()->mOut.Text("Aaaaand nothing happened, because is already holding the " + mHeld->GetName() + ".");
	}

	CheckHoldingItem();

	return result;
}

void ItemHolder::RemoveItem()
{
	mHeld = 0;
	CheckHoldingItem();
}

void ItemHolder::CheckHoldingItem()
{
	//Holding the right item
	if (mHeld == mItemLooking)
	{
		mDescription = mDescriptionBase + " It is holding the " + mHeld->GetName() + ". ";
		mDescription += mCorrectItemDescription;

		Main::Get()->mOut.EndLines(1);
		Main::Get()->mOut.Text(mCorrectItemDescription);
		mCorrectItemHeld = true;

		//Add Score
		if (!mScoreOther)
		{
			mScoreOther = true;
			Main::Get()->mOut.EndLines(1);
			Main::Get()->AddScore(sScoreHoldUse);
		}
	}
	//Holding wrong item
	else if (mHeld != 0)
	{
		mDescription = mDescriptionBase + " It is holding the " + mHeld->GetName() + ". ";
		mCorrectItemHeld = false;
	}
	//Not holding anything
	else
	{
		mDescription = mDescriptionBase + " It is holding nothing.";
		mCorrectItemHeld = false;
	}
}


ItemUse::ItemUse(bool aDestroy, string aName, string aDescription, string aTakeDescription, string aCorrectItemDescription, string aIncorrectItemDescription) : 
			Item(eUse, aName, aDescription, aTakeDescription)
			,mDescriptionBase(aDescription)
			,mCorrectItemDescription(aCorrectItemDescription)
			,mIncorrectItemDescription(aIncorrectItemDescription)
			,mDestroy(aDestroy)
			,mItemLooking(0)
			,mUsed(0)
{
	++sItemHoldUseCount;
	mDescription = mDescriptionBase + " " + mIncorrectItemDescription;
}

void ItemUse::AddItemLooking(Item* aItemLooking)
{
	if (!mItemLooking)
		mItemLooking = aItemLooking;
}

void ItemUse::CheckUse(Item* aUsingItem)
{
	string description;
	description = "You used the " + aUsingItem->GetName() + " on the " + mName;
	//Main::Get()->mOut.Text("You used the " + aUsingItem->GetName() + " on the " + mName);

	if (!mUsed && aUsingItem == mItemLooking)
	{
		mUsed = true;
		mDescription = mDescriptionBase + " " + mCorrectItemDescription;
		description.append(". " + mCorrectItemDescription);
		Main::Get()->mOut.Text(description);
		Use();
		
		//Add Score
		if (!mScoreOther)
		{
			mScoreOther = true;
			Main::Get()->mOut.EndLines(1);
			Main::Get()->AddScore(sScoreHoldUse);
		}

		//Destroy the item if needed
		if (mDestroy)
		{
			Main::Get()->mInventory.remove(mItemLooking);
			delete mItemLooking;
			mItemLooking = 0;
		}

		return;
	}
	else
		description.append(", which did absolutely nothing!");
		//Main::Get()->mOut.Text(", which did absolutely nothing!");

	Main::Get()->mOut.Text(description);

}


UseChest::UseChest(bool aDestroy, string aName, string aDescription, string aTakeDescription, string aCorrectItemDescription, string aIncorrectItemDescription) : 
				ItemUse(aDestroy, aName, aDescription, aTakeDescription, aCorrectItemDescription, aIncorrectItemDescription)
{}

UseChest::~UseChest()
{
	while(!mItems.empty())
	{
		delete mItems.front();
		mItems.pop_front();
	}
}

void UseChest::AddItem(Item* aItem)
{
	if (aItem)
		mItems.push_back(aItem);
}

void UseChest::Use()
{
	Main::Get()->mOut.EndLines(1);
	Main::Get()->mOut.Text("New items in room:");

	for (list<Item*>::iterator i = mItems.begin(); i != mItems.end(); i = mItems.begin())
	{
		Main::Get()->mOut.EndLines(1);
		Main::Get()->mOut.Text("-" + (*i)->GetName());
		Main::Get()->mCurrentRoom->mItems.splice(Main::Get()->mCurrentRoom->mItems.end(), mItems, i);
	}
}


UseLockedDoor::UseLockedDoor(bool aDestroy, string aName, string aDescription, string aTakeDescription, string aCorrectItemDescription, string aIncorrectItemDescription) :
				ItemUse(aDestroy, aName, aDescription, aTakeDescription, aCorrectItemDescription, aIncorrectItemDescription)
				,mExit(0)
				,mExitsRoom(0)
{}

UseLockedDoor::~UseLockedDoor()
{
	if (mExit)
		delete mExit;
}

void UseLockedDoor::AddExit(Exit* aExit, Room* aExitInRoom)
{
	if (aExit && aExitInRoom)
	{
		mExit = aExit;
		mExitsRoom = aExitInRoom;
	}
}

void UseLockedDoor::Use()
{
	mExitsRoom->mExits.push_back(mExit);
	mExit = 0; //It is now the rooms responsibility to clean this exit up.
}