#include "../../mainproc/GameMain.h"
#include "../../netwaker_member/NetWakerClientInc.h"
#include "UnitFrame.h"
#include "ItemClipboard.h"
#include "BagFrame.h"
#include "TradeFrame.h"

int	LuaFunc_GetPlayerTradeItemInfo		(lua_State* L);
int	LuaFunc_GetRecipientTradeItemInfo	(lua_State* L);
int	LuaFunc_PickupPlayerTradeItem		(lua_State* L);
int LuaFunc_GetPlayerTradeMoney			(lua_State* L);
int LuaFunc_GetRecipientTradeMoney		(lua_State* L);
int LuaFunc_TradeConfirm				(lua_State* L);
int LuaFunc_TradeOK						(lua_State* L);
int LuaFunc_CancelTrade					(lua_State* L);
int LuaFunc_RequestTrade				(lua_State* L);
int	LuaFunc_AcceptTrade					(lua_State* L);
int	LuaFunc_DeclineTrade				(lua_State* L);

CTradeFrame*				g_pTradeFrame = NULL;

// ----------------------------------------------------------------------------
CTradeFrame::CTradeFrame(CInterface* object)
	: CInterfaceBase(object)
{		
	Clear();

	g_pTradeFrame	= this;
}

// ----------------------------------------------------------------------------
CTradeFrame::~CTradeFrame()
{
	g_pTradeFrame = NULL;
}

// ----------------------------------------------------------------------------
void CTradeFrame::RegisterFunc()
{
	lua_State* L = GetLuaStateWorld();
	if (L)
	{		
		lua_register(L, "GetPlayerTradeItemInfo",			LuaFunc_GetPlayerTradeItemInfo);
		lua_register(L, "GetRecipientTradeItemInfo",		LuaFunc_GetRecipientTradeItemInfo);
		lua_register(L, "PickupPlayerTradeItem",			LuaFunc_PickupPlayerTradeItem);
		lua_register(L, "GetPlayerTradeMoney",				LuaFunc_GetPlayerTradeMoney);
		lua_register(L, "GetRecipientTradeMoney",			LuaFunc_GetRecipientTradeMoney);
		lua_register(L, "TradeConfirm",						LuaFunc_TradeConfirm);
		lua_register(L, "TradeOK",							LuaFunc_TradeOK);
		lua_register(L, "CancelTrade",						LuaFunc_CancelTrade);
		lua_register(L, "RequestTrade",						LuaFunc_RequestTrade);
		lua_register(L, "AcceptTrade",						LuaFunc_AcceptTrade);
		lua_register(L, "DeclineTrade",						LuaFunc_DeclineTrade);
	}
}

// ----------------------------------------------------------------------------
void CTradeFrame::Update(float elapsedTime)
{
	switch (m_tradeState)
	{
	case eTradeState_Request_Made:
		break;

	case eTradeState_Request_Receive:
		m_time += elapsedTime;
		if ( m_time > 600.0f )
			Cancel();
		break;

	case eTradeState_Agree:
		break;

	case eTradeState_Disagree:
		break;

	case eTradeState_Traded:
		break;
	}
}

// ----------------------------------------------------------------------------
int CTradeFrame::SetProcess(TradeState state, int playerId, const char* name)
{
	lua_State* L = GetLuaStateWorld();

	switch(state)
	{
	case eTradeState_Request_Made:
		if (m_tradeState != eTradeState_None && m_tradeState != eTradeState_Request_Made)
			return -2;										// 未處於無狀態下,不能發出交易申請

		NetCli_Trade::S_RequestTrade( playerId );
		break;

	case eTradeState_Request_Receive:
		if (m_tradeState != eTradeState_None)
			return -2;										// 回應對方自己忙碌中
		
		// 送出訊問事件,是否願意與對交易
		lua_pushstring(L, name);
		lua_setglobal(L, "arg1");
		SendWorldEvent("TRADE_REQUEST");
		break;

	case eTradeState_Agree:
		if (m_tradeState != eTradeState_Request_Receive)	
			return -2;										// 未被要求交易

		NetCli_Trade::S_AgreeTrade(playerId, true);
		break;

	case eTradeState_Disagree:
		if (m_tradeState != eTradeState_Request_Receive)	
			return -2;										// 未被要求交易	
		state = eTradeState_None;
		playerId = 0;
		NetCli_Trade::S_AgreeTrade(playerId, false);
		break;

	case eTradeState_Traded:
		if (m_tradeState != eTradeState_Request_Made && m_tradeState != eTradeState_Agree)
			return -1;										// 流程錯誤

		SendWorldEvent("TRADE_BEGIN");
		break;

	default:
		return -1;
	}

	m_tradeState	= state;
	m_time			= 0.0f;
	m_playerId		= playerId;	
	return 0;
}

// ----------------------------------------------------------------------------
void CTradeFrame::Cancel()
{
	switch(m_tradeState)
	{
	case eTradeState_Request_Made:
		break;

	case eTradeState_Request_Receive:
		NetCli_Trade::S_AgreeTrade(m_playerId, false);
		break;

	case eTradeState_Agree:
		break;

	case eTradeState_Disagree:
		break;

	case eTradeState_Traded:
		NetCli_Trade::S_StopTrade(m_playerId);
		break;
	}	
	Clear();
	NetCli_TradeChild::ClearItem();

	CUiFrame* frame = (CUiFrame*)m_interface->GetUiWorld()->FindObject("TradeFrame");
	if ( frame )
		frame->SetVisible(false);
}

// ----------------------------------------------------------------------------
int	CTradeFrame::PlayerItemLock()
{
	if ( !m_isConfirm )
	{
		m_isConfirm = true;
		NetCli_Trade::S_ItemOK();

		lua_State* L = m_interface->GetUiWorld()->GetLuaState();
		if ( L )
		{
			lua_pushstring(L, "LOCK");
			lua_setglobal(L, "arg1");
			SendWorldEvent(UiEvent_TradePlayerItemState);
		}
		return 0;
	}
	return -1;
}

// ----------------------------------------------------------------------------
int	CTradeFrame::PlayerItemUnlock()
{
	if ( m_isConfirm )
	{
		m_isConfirm = false;

		lua_State* L = m_interface->GetUiWorld()->GetLuaState();
		if ( L )
		{
			lua_pushstring(L, "UNLOCK");
			lua_setglobal(L, "arg1");
			SendWorldEvent(UiEvent_TradePlayerItemState);
		}
		return 0;
	}
	return -1;
}

// ----------------------------------------------------------------------------
int	CTradeFrame::RecipientItemLock()
{
	lua_State* L = m_interface->GetUiWorld()->GetLuaState();
	if ( L )
	{
		lua_pushstring(L, "LOCK");
		lua_setglobal(L, "arg1");
		SendWorldEvent(UiEvent_TradeRecipientItemState);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int CTradeFrame::RecipientItemUnlock()
{
	lua_State* L = m_interface->GetUiWorld()->GetLuaState();
	if ( L )
	{
		lua_pushstring(L, "UNLOCK");
		lua_setglobal(L, "arg1");
		SendWorldEvent(UiEvent_TradeRecipientItemState);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int CTradeFrame::Trade()
{
	if (m_tradeState == eTradeState_Traded && m_isConfirm)
	{
		NetCli_Trade::S_FinalOK();
		return 0;
	}
	return -1;
}

// ----------------------------------------------------------------------------
TradeItem* CTradeFrame::GetItem(int index)
{
	if (index >= 0 && index < TRADE_ITEM_MAX_SIZE)
		return &m_items[index];
	return NULL;
}

// ----------------------------------------------------------------------------
void CTradeFrame::Cut(int index)
{
	RoleDataEx* role = CNetGlobal::RoleData();
	TradeItem* tradeItem = GetItem(index);

	if ( tradeItem )
	{
		switch( tradeItem->type )
		{
		case eTradeItemType_None:
			break;

		case eTradeItemType_Bag:
			{
				ItemFieldStruct* item = role->GetBodyItem( tradeItem->pos );
				if ( item )
				{
					NetCli_Trade::S_PutItem(EM_ItemState_NONE, tradeItem->pos, *item);
					g_pBagFrame->Cut( tradeItem->pos );
				}
				
				/*
				ItemFieldStruct* item = role->GetBodyItem( tradeItem->pos );
				if ( item )
				{
					NetCli_Trade::S_PutItem(EM_ItemState_NONE, tradeItem->pos, *item);
					GameObjDbStruct* itemDB = CNetGlobal::GetObj( item->OrgObjID );
					if ( itemDB )
					{
						g_pItemClipboard->SetFile( itemDB->ImageObj->ACTField );
						g_pItemClipboard->PickupTrade( tradeItem->type, tradeItem->pos, tradeItem->id );
					}
				}
				*/
			}
			break;

		case eTradeItemType_Bank:
		case eTradeItemType_Equipment:			
			break;
		}
	}

	// 清除項目會由SERVER通知
}

// ----------------------------------------------------------------------------
void CTradeFrame::Paste(int index)
{	
	TradeItem* tradeItem = GetItem(index);

	if ( tradeItem && !m_isConfirm)
	{
		switch( g_pItemClipboard->GetType() )
		{
		case CItemClipboard::eItem_Type_None:			// 拿取物品
			Cut(index);
			break;

		case CItemClipboard::eItem_Type_Bag:			// 背包 -> 交易
			{
				ClipboardBagItem backpack = g_pItemClipboard->GetBagItem();
				PutItem(eTradeItemType_Bag, index, backpack.pos);

				if ( tradeItem->type != eTradeItemType_None )
					Cut(index);
				else
					g_pItemClipboard->Clear();				
			}
			break;

		case CItemClipboard::eItem_Type_Trade:			// 交易 -> 交易
			{
				ClipboardTradeItem trade = g_pItemClipboard->GetTradeItem();
				PutItem(trade.type, index, trade.pos);

				if ( tradeItem->type != eTradeItemType_None )
					Cut(index);
				else
					g_pItemClipboard->Clear();				
			}
			break;

			/*
		case CItemClipboard::eItem_Type_Bankpack:		// 銀行 -> 交易
			{
				ClipboardBankpackItem& bankpack = g_pItemClipboard->GetBankpackItem();
				if ( tradeItem->type != eTradeItemType_None )
					Cut(index);
				else
					g_pItemClipboard->Clear();

				tradeItem->type	= eTradeItemType_Bank;
				tradeItem->id	= bankpack.itemID;
				tradeItem->pos	= bankpack.pos;
			}
			break;

		case CItemClipboard::eItem_Type_Equipment:		// 裝備 -> 交易
			{
				ClipboardEquipmentItem equipment = g_pItemClipboard->GetEquipmentItem();
				if ( tradeItem->type != eTradeItemType_None )
					Cut(index);
				else
					g_pItemClipboard->Clear();

				tradeItem->type	= eTradeItemType_Equipment;
				tradeItem->id	= equipment.itemID;
				tradeItem->pos	= equipment.pos;
			}
			break;		

		case CItemClipboard::eItem_Type_Action:			// 快捷 -> 交易
			break;

		case CItemClipboard::eItem_Type_Shop:
			break;

		case CItemClipboard::eItem_Type_Trade:
			break;

		case CItemClipboard::eItem_Type_Skill:
			break;
			*/
		}
	}
}


// ----------------------------------------------------------------------------
void CTradeFrame::PutItem(int type, int index, int pos)
{
	ItemFieldStruct* item = NULL;

	switch (type)
	{
	case eTradeItemType_Bag:
		{
			RoleDataEx* role = CNetGlobal::RoleData();
			item = role->GetBodyItem(pos);
		}
		break;

	case eTradeItemType_Bank:
		break;

	case eTradeItemType_Equipment:
		break;
	}

	if ( item )
	{
		switch (index)
		{
		case 0:
			item->Pos = EM_TRADE_ITEM1;
			break;
		case 1:
			item->Pos = EM_TRADE_ITEM2;
			break;
		case 2:
			item->Pos = EM_TRADE_ITEM3;
			break;
		case 3:
			item->Pos = EM_TRADE_ITEM4;
			break;
		case 4:
			item->Pos = EM_TRADE_ITEM5;
			break;
		case 5:
			item->Pos = EM_TRADE_ITEM6;
			break;
		case 6:
			item->Pos = EM_TRADE_ITEM7;
			break;
		case 7:
			item->Pos = EM_TRADE_ITEM8;
			break;
		}

		switch (type)
		{
		case eTradeItemType_Bag:
			NetCli_Trade::S_PutItem(item->Pos, pos, *item);
			break;

		case eTradeItemType_Bank:
			break;

		case eTradeItemType_Equipment:
			break;
		}		
	}
}

// ----------------------------------------------------------------------------
void CTradeFrame::Clear()
{
	m_playerId		= 0;
	m_money			= 0;
	m_isConfirm		= false;
	m_time			= 0.0f;
	m_tradeState	= eTradeState_None;

	RoleDataEx* role = CNetGlobal::RoleData();
	for ( int j = 0; j < role->BaseData.Body.Count; j++ )
	{
		ItemFieldStruct* item = role->GetBodyItem(j);
		if (item && item->Pos >= EM_TRADE_ITEM1 && item->Pos <= EM_TRADE_ITEM8 )
			item->Pos = EM_ItemState_NONE;
	}

	ClearItem();	
}

// ----------------------------------------------------------------------------
void CTradeFrame::ClearItem()
{
	memset(m_items, 0, sizeof(m_items));
}

// ----------------------------------------------------------------------------
void CTradeFrame::Refresh()
{
	RoleDataEx* role = CNetGlobal::RoleData();

	ClearItem();
	for ( int j = 0; j < role->BaseData.Body.Count; j++ )
	{
		ItemFieldStruct* item = role->GetBodyItem(j);
		if (item && item->Pos >= EM_TRADE_ITEM1 && item->Pos <= EM_TRADE_ITEM8 )
		{
			TradeItem* tradeItem = GetItem(item->Pos - EM_TRADE_ITEM1);
			if ( tradeItem && tradeItem->type == eTradeItemType_None )
			{
				tradeItem->type		= eTradeItemType_Bag;
				tradeItem->id		= item->OrgObjID;
				tradeItem->pos		= j;
			}
		}
	}
}

// ----------------------------------------------------------------------------
int	LuaFunc_GetPlayerTradeItemInfo(lua_State* L)
{
	TradeItem* tradeItem = g_pTradeFrame->GetItem(luaL_checkint(L, 1) - 1);
	if ( tradeItem )
	{
		RoleDataEx* role = CNetGlobal::RoleData();
		switch ( tradeItem->type )
		{
		case eTradeItemType_None:
			break;

		case eTradeItemType_Bag:
			{
				ItemFieldStruct* item = role->GetBodyItem(tradeItem->pos);
				if ( item )
				{
					GameObjDbStruct* itemDB = CNetGlobal::GetObj( item->OrgObjID );
					if ( itemDB )
					{
						lua_pushstring(L, itemDB->ImageObj->ACTField);
						lua_pushstring(L, itemDB->Name);
						lua_pushnumber(L, item->Count);		
						return 3;
					}
				}
			}
			break;

		case eTradeItemType_Bank:
			break;

		case eTradeItemType_Equipment:
			break;
		}
	}

	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetRecipientTradeItemInfo(lua_State* L)
{
	ItemFieldStruct* item = NetCli_TradeChild::GetTradeItem(luaL_checkint(L, 1) - 1);
	if ( item && !item->IsEmpty() )
	{
		GameObjDbStruct* itemDB = CNetGlobal::GetObj( item->OrgObjID );
		if ( itemDB )
		{
			lua_pushstring(L, itemDB->ImageObj->ACTField);
			lua_pushstring(L, itemDB->Name);
			lua_pushnumber(L, item->Count);
			return 3;
		}
	}

	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_PickupPlayerTradeItem(lua_State* L)
{
	g_pTradeFrame->Paste(luaL_checkint(L, 1) - 1);
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetPlayerTradeMoney(lua_State* L)
{
	lua_pushnumber(L, g_pTradeFrame->GetTradeMoney());
	return 1;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetRecipientTradeMoney(lua_State* L)
{
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_TradeConfirm(lua_State* L)
{
	g_pTradeFrame->PlayerItemLock();
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_TradeOK(lua_State* L)
{
	g_pTradeFrame->Trade();
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_CancelTrade(lua_State* L)
{
	g_pTradeFrame->Cancel();
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_RequestTrade (lua_State* L)
{
	int index;
	int id = -1;

	switch ( CUnitFrame::GetUnitType(luaL_checkstring(L, 1), index) )
	{	
	case CUnitFrame::eUnit_Player:
		{
			CRoleSprite* player = g_pGameMain->GetPlayer();
			if ( player )
				id = player->GetIdentify();				
		}
		break;

	case CUnitFrame::eUnit_Target:
		{
			CRoleSprite* target = g_pGameMain->GetTargetPlayer();
			if ( target )
				id = target->GetIdentify();
		}
		break;

	case CUnitFrame::eUnit_Party:
		{
			PartyMemberInfo* member = NetCli_PartyChild::GetPartyMember(index - 1);
			if ( member )
				id = member->GItemID;
		}
		break;

	case CUnitFrame::eUnit_Raid:
		break;

	case CUnitFrame::eUnit_Pet:
		break;
	}

	if ( id != -1 )
	{
		g_pTradeFrame->SetProcess(eTradeState_Request_Made, id);
	}
	return 0;	
}

// ----------------------------------------------------------------------------
int	LuaFunc_AcceptTrade(lua_State* L)
{
	g_pTradeFrame->SetProcess(eTradeState_Agree, g_pTradeFrame->GetPlayerId());
	return 0;
}

// ----------------------------------------------------------------------------
int	LuaFunc_DeclineTrade(lua_State* L)
{
	g_pTradeFrame->SetProcess(eTradeState_Disagree, 0);
	return 0;
}