#include "stdafx.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.item.trading.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h"
#include "..\..\Minecraft.h"
#include "..\..\MultiPlayerLocalPlayer.h"
#include "..\..\ClientConnection.h"
#include "IUIScene_TradingMenu.h"

IUIScene_TradingMenu::IUIScene_TradingMenu()
{
	m_validOffersCount = 0;
	m_selectedSlot = 0;
	m_offersStartIndex = 0;
	m_menu = NULL;
	m_bHasUpdatedOnce = false;
}

shared_ptr<Merchant> IUIScene_TradingMenu::getMerchant()
{
	return m_merchant;
}

bool IUIScene_TradingMenu::handleKeyDown(int iPad, int iAction, bool bRepeat)
{
	bool handled = false;
	//MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);

	bool changed = false;

	Minecraft *pMinecraft = Minecraft::GetInstance();

	if( pMinecraft->localgameModes[getPad()] != NULL )
	{
		Tutorial *tutorial = pMinecraft->localgameModes[getPad()]->getTutorial();
		if(tutorial != NULL)
		{
			tutorial->handleUIInput(iAction);
			if(ui.IsTutorialVisible(getPad()) && !tutorial->isInputAllowed(iAction))
			{
				return S_OK;
			}
		}
	}


	switch(iAction)
	{
	case ACTION_MENU_B:		
		ui.ShowTooltip( iPad, eToolTipButtonX, false );
		ui.ShowTooltip( iPad, eToolTipButtonB, false );
		ui.ShowTooltip( iPad, eToolTipButtonA, false );	
		ui.ShowTooltip( iPad, eToolTipButtonRB, false );	
		// kill the crafting xui
		//ui.PlayUISFX(eSFX_Back);
		ui.CloseUIScenes(iPad);

		handled = true;
		break;
	case ACTION_MENU_A:
		if(!m_activeOffers.empty())
		{
			int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
			if( selectedShopItem < m_activeOffers.size() )
			{
				MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first;
				if(!activeRecipe->isDeprecated())
				{
					// Do we have the ingredients?
					shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem();
					shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem();
					shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
					int buyAMatches = player->inventory->countMatches(buyAItem);
					int buyBMatches = player->inventory->countMatches(buyBItem);
					if( (buyAItem != NULL && buyAMatches >= buyAItem->count) && (buyBItem == NULL || buyBMatches >= buyBItem->count) )
					{
						m_merchant->notifyTrade(activeRecipe);

						// Remove the items we are purchasing with
						player->inventory->removeResources(buyAItem);
						player->inventory->removeResources(buyBItem);

						// Add the item we have purchased
						shared_ptr<ItemInstance> result = activeRecipe->getSellItem()->copy();
						if(!player->inventory->add( result ) )
						{
							player->drop(result);
						}

						// Send a packet to the server
						int actualShopItem = m_activeOffers.at(selectedShopItem).second;
						player->connection->send( shared_ptr<TradeItemPacket>( new TradeItemPacket(m_menu->containerId, actualShopItem) ) );

						updateDisplay();
					}
				}
			}
		}
		handled = true;
		break;
	case ACTION_MENU_LEFT:
		handled = true;
		if(m_selectedSlot == 0)
		{
			if(m_offersStartIndex > 0)
			{
				--m_offersStartIndex;
				changed = true;
			}
		}
		else
		{
			--m_selectedSlot;
			changed = true;
			moveSelector(false);
		}
		break;
	case ACTION_MENU_RIGHT:
		handled = true;
		if(m_selectedSlot == (DISPLAY_TRADES_COUNT - 1))
		{
			if((m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size())
			{
				++m_offersStartIndex;
				changed = true;
			}
		}
		else
		{
			++m_selectedSlot;
			changed = true;
			moveSelector(true);
		}
		break;
	}
	if (changed)
	{
		updateDisplay();

		int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
		if( selectedShopItem < m_activeOffers.size() )
		{
			int actualShopItem = m_activeOffers.at(selectedShopItem).second;
			m_menu->setSelectionHint(actualShopItem);

			ByteArrayOutputStream rawOutput;
			DataOutputStream output(&rawOutput);
			output.writeInt(actualShopItem);
			Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray())));
		}
	}
	return handled;
}

void IUIScene_TradingMenu::handleTick()
{
	int offerCount = 0;
	MerchantRecipeList *offers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);
	if (offers != NULL)
	{
		offerCount = offers->size();

		if(!m_bHasUpdatedOnce)
		{
			updateDisplay();
		}
	}

	showScrollRightArrow( (m_offersStartIndex + DISPLAY_TRADES_COUNT) < m_activeOffers.size());
	showScrollLeftArrow(m_offersStartIndex > 0);
}

void IUIScene_TradingMenu::updateDisplay()
{
	int iA = -1;

	MerchantRecipeList *unfilteredOffers = m_merchant->getOffers(Minecraft::GetInstance()->localplayers[getPad()]);
	if (unfilteredOffers != NULL)
	{
		m_activeOffers.clear();
		int unfilteredIndex = 0;
		int firstValidTrade = INT_MAX;
		for(AUTO_VAR(it, unfilteredOffers->begin()); it != unfilteredOffers->end(); ++it)
		{
			MerchantRecipe *recipe = *it;
			if(!recipe->isDeprecated())
			{
				m_activeOffers.push_back( pair<MerchantRecipe *,int>(recipe,unfilteredIndex));
				firstValidTrade = min(firstValidTrade,unfilteredIndex);
			}
			++unfilteredIndex;
		}

		if(!m_bHasUpdatedOnce)
		{
			if(firstValidTrade != 0 && firstValidTrade < unfilteredOffers->size())
			{
				m_menu->setSelectionHint(firstValidTrade);

				ByteArrayOutputStream rawOutput;
				DataOutputStream output(&rawOutput);
				output.writeInt(firstValidTrade);
				Minecraft::GetInstance()->getConnection(getPad())->send(shared_ptr<CustomPayloadPacket>( new CustomPayloadPacket(CustomPayloadPacket::TRADER_SELECTION_PACKET, rawOutput.toByteArray())));
			}
		}

		if( (m_offersStartIndex + DISPLAY_TRADES_COUNT) > m_activeOffers.size())
		{
			m_offersStartIndex = m_activeOffers.size() - DISPLAY_TRADES_COUNT;
			if(m_offersStartIndex < 0) m_offersStartIndex = 0;
		}

		for(unsigned int i = 0; i < DISPLAY_TRADES_COUNT; ++i)
		{
			int offerIndex = i + m_offersStartIndex;
			bool showRedBox = false;
			if(offerIndex < m_activeOffers.size())
			{
				showRedBox = !canMake(m_activeOffers.at(offerIndex).first);
				setTradeItem(i, m_activeOffers.at(offerIndex).first->getSellItem() );
			}
			else
			{
				setTradeItem(i, nullptr);
			}
			setTradeRedBox( i, showRedBox);
		}

		int selectedShopItem = (m_selectedSlot + m_offersStartIndex);
		if( selectedShopItem < m_activeOffers.size() )
		{
			MerchantRecipe *activeRecipe = m_activeOffers.at(selectedShopItem).first;

			wstring wsTemp;

			// 4J-PB - need to get the villager type here
			wsTemp = app.GetString(IDS_VILLAGER_OFFERS_ITEM);
			wsTemp = replaceAll(wsTemp,L"{*VILLAGER_TYPE*}",app.GetString(m_merchant->getDisplayName()));
			int iPos=wsTemp.find(L"%s");
			wsTemp.replace(iPos,2,activeRecipe->getSellItem()->getHoverName());

			setTitle(wsTemp.c_str());

			vector<wstring> unformattedStrings;
			wstring offerDescription = GetItemDescription(activeRecipe->getSellItem(), unformattedStrings);
			setOfferDescription(offerDescription, unformattedStrings);
			
			shared_ptr<ItemInstance> buyAItem = activeRecipe->getBuyAItem();
			shared_ptr<ItemInstance> buyBItem = activeRecipe->getBuyBItem();

			setRequest1Item(buyAItem);
			setRequest2Item(buyBItem);

			if(buyAItem != NULL) setRequest1Name(buyAItem->getHoverName());
			else setRequest1Name(L"");

			if(buyBItem != NULL) setRequest2Name(buyBItem->getHoverName());
			else setRequest2Name(L"");

			bool canMake = true;

			shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
			int buyAMatches = player->inventory->countMatches(buyAItem);
			if(buyAMatches > 0)
			{
				setRequest1RedBox(buyAMatches < buyAItem->count);
				canMake = buyAMatches > buyAItem->count;
			}
			else
			{
				setRequest1RedBox(true);
				canMake = false;
			}

			int buyBMatches = player->inventory->countMatches(buyBItem);
			if(buyBMatches > 0)
			{
				setRequest2RedBox(buyBMatches < buyBItem->count);
				canMake = canMake && buyBMatches > buyBItem->count;
			}
			else
			{
				if(buyBItem!=NULL)
				{
					setRequest2RedBox(true);
					canMake = false;
				}
				else
				{
					setRequest2RedBox(buyBItem != NULL);
					canMake = canMake && buyBItem == NULL;
				}
			}

			if(canMake) iA = IDS_TOOLTIPS_TRADE;
		}
		else
		{
			setTitle(app.GetString(m_merchant->getDisplayName()));
			setRequest1Name(L"");
			setRequest2Name(L"");
			setRequest1RedBox(false);
			setRequest2RedBox(false);
			setRequest1Item(nullptr);
			setRequest2Item(nullptr);
		}

		m_bHasUpdatedOnce = true;
	}

	ui.SetTooltips(getPad(), iA, IDS_TOOLTIPS_EXIT);
}

bool IUIScene_TradingMenu::canMake(MerchantRecipe *recipe)
{
	bool canMake = false;
	if (recipe != NULL)
	{
		if(recipe->isDeprecated()) return false;

		shared_ptr<ItemInstance> buyAItem = recipe->getBuyAItem();
		shared_ptr<ItemInstance> buyBItem = recipe->getBuyBItem();

		shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->localplayers[getPad()];
		int buyAMatches = player->inventory->countMatches(buyAItem);
		if(buyAMatches > 0)
		{
			canMake = buyAMatches >= buyAItem->count;
		}
		else
		{
			canMake = buyAItem == NULL;
		}

		int buyBMatches = player->inventory->countMatches(buyBItem);
		if(buyBMatches > 0)
		{
			canMake = canMake && buyBMatches >= buyBItem->count;
		}
		else
		{
			canMake = canMake && buyBItem == NULL;
		}
	}
	return canMake;
}


void IUIScene_TradingMenu::setRequest1Item(shared_ptr<ItemInstance> item)
{
}

void IUIScene_TradingMenu::setRequest2Item(shared_ptr<ItemInstance> item)
{
}

void IUIScene_TradingMenu::setTradeItem(int index, shared_ptr<ItemInstance> item)
{
}

wstring IUIScene_TradingMenu::GetItemDescription(shared_ptr<ItemInstance> item, vector<wstring> &unformattedStrings)
{
	if(item == NULL) return L"";

	wstring desc = L"";
	vector<wstring> *strings = item->getHoverTextOnly(nullptr, false, unformattedStrings);
	bool firstLine = true;
	for(AUTO_VAR(it, strings->begin()); it != strings->end(); ++it)
	{
		wstring thisString = *it;
		if(!firstLine)
		{
			desc.append( L"<br />" );
		}
		else
		{
			firstLine = false;
		}
		desc.append( thisString );
	}
	strings->clear();
	delete strings;
	return desc;
}
