#include <windows.h>
#include <shlwapi.h>
#include "Login/LoginParent.h"
#include "Login/AccountLogin.h"
#include "Login/CharacterSelect.h"
#include "Login/CharacterCreate.h"
#include "Debug/DebugMessage.h"
#include "WorldFrames/GameControl.h"
#include "WorldFrames/UnitFrame.h"
#include "WorldFrames/MoneyFrame.h"
#include "WorldFrames/ChatFrame.h"
#include "WorldFrames/ChatEdit.h"
#include "WorldFrames/BagFrame.h"
#include "WorldFrames/BankFrame.h"
#include "WorldFrames/StoreFrame.h"
#include "WorldFrames/ItemClipboard.h"
#include "WorldFrames/MacroFrame.h"
#include "WorldFrames/ActionFrame.h"
#include "WorldFrames/Equipment.h"
#include "WorldFrames/TradeFrame.h"
#include "WorldFrames/GameTooltip.h"
#include "WorldFrames/WorldMap.h"
#include "WorldFrames/BuffFrame.h"
#include "WorldFrames/PartyFrame.h"
#include "WorldFrames/LootFrame.h"
#include "WorldFrames/UI_CharHeadFrame.h"
#include "WorldFrames/MailFrame.h"
#include "WorldFrames/AuctionFrame.h"
#include "WorldFrames/FriendFrame.h"
#include "Maintain/Maintain.h"
#include "Quest/UI_QuestList.h"
#include "Quest/UI_QuestBook.h"
#include "Quest/UI_QuestDetail.h"
#include "SkillBook/UI_SkillBook.h"
#include "Minimap/Minimap.h"
#include "MessageBox/MessageBox.h"

#include "interface.h"

CInterface*					g_pInterface;

int	LuaFunc_GetGlobal			(lua_State *L);
int LuaFunc_ErrorOutput			(lua_State* L);
int	LuaFunc_GetDefaultLanguage	(lua_State* L);
int	LuaFunc_RunScript			(lua_State* L);

// ----------------------------------------------------------------------------------
CInterfaceBase::CInterfaceBase(CInterface* object)
{
	m_interface = object;
}

// ----------------------------------------------------------------------------------
CInterfaceBase::~CInterfaceBase()
{
	m_interface = NULL;
}

// ----------------------------------------------------------------------------------
lua_State* CInterfaceBase::GetLuaStateLogin()
{
	return (m_interface) ? m_interface->GetUiLogin()->GetLuaState() : NULL;
}

// ----------------------------------------------------------------------------------
lua_State* CInterfaceBase::GetLuaStateWorld()
{
	return (m_interface) ? m_interface->GetUiWorld()->GetLuaState() : NULL;
}

// ----------------------------------------------------------------------------------
void CInterfaceBase::SendLoginEvent(const char* event)
{
	CUi* ui = m_interface->GetUiLogin();
	if ( ui )
		ui->SendEvent(event);
}

// ----------------------------------------------------------------------------------
void CInterfaceBase::SendWorldEvent(const char* event)
{
	CUi* ui = m_interface->GetUiWorld();
	if ( ui )
		ui->SendEvent(event);
}

// ----------------------------------------------------------------------------------
bool CInterfaceBase::GetGlobalPath(const char* name, char* outPath, int outSize)
{
	if ( name == NULL || outPath == NULL || outSize <= 0 )
		return false;

	const char* savePath = m_interface->GetSavePath();
	char tmp[1024];
	
	memset( tmp, 0, sizeof(tmp) );
	if ( savePath[0] >= 32 )
		sprintf( tmp, "%s\\%s", savePath, name );
	else
		strcpy( tmp, name );

	strncpy( outPath, tmp, outSize );
	outPath[outSize - 1] = 0;
	return true;
}

// ----------------------------------------------------------------------------------
bool CInterfaceBase::GetLocalPath(const char* name, char* outPath, int outSize)
{
	if ( name == NULL || outPath == NULL || outSize <= 0 )
		return false;

	const char* savePath = m_interface->GetSavePath();
	const char* playerName = m_interface->GetPlayerName();
	char tmp[1024];

	memset( tmp, 0, sizeof(tmp) );
	if ( savePath[0] >= 32 )
		sprintf( tmp, "%s\\%s\\%s", savePath, playerName, name );
	else
		sprintf( tmp, "%s\\%s", playerName, name );

	strncpy( outPath, tmp, outSize );
	outPath[outSize - 1] = 0;
	return true;
}

// ----------------------------------------------------------------------------------
CInterface::CInterface(const char* resourcePath)
{
	m_processType	= 0;
	m_uiLogin		= new CUi;
	m_uiWorld		= new CUi;
	m_isVisible		= true;
	m_isEnable		= true;

	m_playerName.empty();

	SetResourcePath(resourcePath);

	g_pInterface	= this;

	// new interface class
	// login frames
	m_loginFrames.push_back( new CLoginParent (this)			);
	m_loginFrames.push_back( new CAccountLogin (this)			);
	m_loginFrames.push_back( new CCharacterSelect (this)		);
	m_loginFrames.push_back( new CCharacterCreate (this)		);

	// world frames
	m_worldFrames.push_back( new CGameControl (this)			);
	m_worldFrames.push_back( new CUnitFrame (this)				);
	m_worldFrames.push_back( new CMoneyFrame (this)				);	
	m_worldFrames.push_back( new CItemClipboard (this)			);	
	m_worldFrames.push_back( new CGameTooltip (this)			);
	m_worldFrames.push_back( new CChatFrame (this)				);
	m_worldFrames.push_back( new CChatEdit (this)				);
	m_worldFrames.push_back( new CBagFrame (this)				);
	m_worldFrames.push_back( new CBankFrame (this)				);
	m_worldFrames.push_back( new CStoreFrame (this)				);
	m_worldFrames.push_back( new CDebugMessage (this)			);
	m_worldFrames.push_back( new CMacroFrame (this)				);
	m_worldFrames.push_back( new CActionFrame (this)			);
	
	m_worldFrames.push_back( new CUI_QuestList( this )			);
	m_worldFrames.push_back( new CUI_QuestBook( this )			);
	m_worldFrames.push_back( new CUI_QuestDetail( this )		);
	
	m_worldFrames.push_back( new CUI_CharHeadFrame( this )		);
	m_worldFrames.push_back( new CMaintain (this)				);
	m_worldFrames.push_back( new CEquipment (this)				);
	m_worldFrames.push_back( new CTradeFrame (this)				);

//	m_worldFrames.push_back( new CUI_SkillBook (this)			);
	m_worldFrames.push_back( new CBuffFrame (this)				);
	m_worldFrames.push_back( new CPartyFrame (this)				);
	m_worldFrames.push_back( new CLootFrame (this)				);
	m_worldFrames.push_back( new CMinimapFrame (this)			);
	m_worldFrames.push_back( new CMessageBox(this)				);
	m_worldFrames.push_back( new CMailFrame(this)				);
	m_worldFrames.push_back( new CAuctionFrame(this)			);

	m_worldFrames.push_back( new CFriendFrame(this)				);

	m_worldFrames.push_back( new CWorldMapFrame(this)			);
	//m_uiMember.push_back(new CWorldFrame(this));

	m_savePath = INTERFACE_SAVE_PATH;

	if ( !m_savePath.empty() )
	{
		CreateDirectory(m_savePath.c_str(), NULL);			// 建立目錄
	}
}

// ----------------------------------------------------------------------------------
CInterface::~CInterface()
{
	SavePlayerData();

	// release interface class
	for (vector<CInterfaceBase*>::iterator iter = m_loginFrames.begin(); iter != m_loginFrames.end(); iter++)
		UI_SAFE_DELETE(*iter);
	m_loginFrames.clear();

	// release interface class
	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		UI_SAFE_DELETE(*iter);
	m_worldFrames.clear();

	UI_SAFE_DELETE(m_uiLogin);
	UI_SAFE_DELETE(m_uiWorld);
}

// ----------------------------------------------------------------------------------
void CInterface::BuildFramesLogin(int width, int height)
{
	string tmp;

	CreateUiLogin(width, height);
	
	// register lua function
	RegisterFunc(m_uiLogin->GetLuaState());
	for (vector<CInterfaceBase*>::iterator iter = m_loginFrames.begin(); iter != m_loginFrames.end(); iter++)
		(*iter)->RegisterFunc();

	// Login
	tmp = m_resourcePath + "interface\\LoginXML\\LoginXML.toc";
	LoadFiles(m_uiLogin, tmp.c_str());

	m_uiLogin->BuildFrames();

	/*
	// load data
	for (vector<CInterfaceBase*>::iterator iter = m_loginFrames.begin(); iter != m_loginFrames.end(); iter++)
		(*iter)->Load();
	*/
}

// ----------------------------------------------------------------------------------
void CInterface::BuildFramesWorld(int width, int height)
{
	string tmp;

	CreateUiWorld(width, height);

	// register lua function
	RegisterFunc(m_uiWorld->GetLuaState());
	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		(*iter)->RegisterFunc();

	// World
	tmp = m_resourcePath + "interface\\WorldXML\\WorldXML.toc";
	LoadFiles(m_uiWorld, tmp.c_str());

	// AddOns
	tmp = m_resourcePath + "interface\\AddOns";
	LoadFolders(m_uiWorld, tmp.c_str());

	m_uiWorld->BuildFrames();

	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		(*iter)->BuildFrames();

	// load data
	// Load();
}

// ----------------------------------------------------------------------------------
void CInterface::RegisterFunc(lua_State* L)
{	
	if (L)
	{
		lua_register(L, "err_output",			LuaFunc_ErrorOutput);
		lua_register(L, "getglobal",			LuaFunc_GetGlobal);
		lua_register(L, "GetDefaultLanguage",	LuaFunc_GetDefaultLanguage);
		lua_register(L, "RunScript",			LuaFunc_RunScript);
	}
}

// ----------------------------------------------------------------------------------
bool CInterface::WndProc(UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	CUi* ui = GetUi();
	if (m_isEnable && ui)
	{
		if (ui == m_uiLogin)
			return ui->MsgProc(iMsg, wParam, lParam);
		else if (ui->MsgProc(iMsg, wParam, lParam))
			return true;
		else
			return g_pGameControl->MsgProc(iMsg, wParam, lParam);
	}
	return false;
}

// ----------------------------------------------------------------------------------
void CInterface::Update(float elapsedTime, InputState &state)
{
	CUi* ui = GetUi();

	if (m_isEnable && ui)
		ui->Update(elapsedTime, state);

	for (vector<CInterfaceBase*>::iterator iter = m_loginFrames.begin(); iter != m_loginFrames.end(); iter++)
		(*iter)->Update(elapsedTime);

	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		(*iter)->Update(elapsedTime);
}

// ----------------------------------------------------------------------------------
void CInterface::Render2D()
{
	CUi* ui = GetUi();
	if (m_isVisible && ui)
		ui->Render2D();
}

// ----------------------------------------------------------------------------------
void CInterface::Render3D()
{
	CUi* ui = GetUi();
	if (m_isVisible && ui)
		ui->Render3D();
}

// ----------------------------------------------------------------------------------
void CInterface::SetScreenSize(float x, float y)
{
	m_uiLogin->SetScreenSize(CUiSize(x, y));
	m_uiWorld->SetScreenSize(CUiSize(x, y));
}

// ----------------------------------------------------------------------------------
void CInterface::SetResourcePath(const char* resourcePath)
{
	m_resourcePath.clear();	

	if (resourcePath && resourcePath[0])
	{
		m_resourcePath = resourcePath;
		if (m_resourcePath[m_resourcePath.size() - 1] != '\\')
			m_resourcePath += "\\";
	}	
}

// ----------------------------------------------------------------------------------
CUi* CInterface::GetUi()
{
	switch(m_processType)
	{
	case eIntreface_Process_Login:
		return m_uiLogin;

	case eIntreface_Process_World:
		return m_uiWorld;
	}
	return NULL;
}

// ----------------------------------------------------------------------------------
CUiInput* CInterface::GetUiInput()
{
	CUi* ui = GetUi();
	if (ui)
		return ui->GetUiInput();
	return NULL;
}

// ----------------------------------------------------------------------------------
void CInterface::SetProcessType(int type)
{
	m_processType = type;

	switch ( m_processType )
	{
	case eIntreface_Process_Login:
		break;

	case eIntreface_Process_World:
		LoadPlayerData();
		break;
	}
}

// ----------------------------------------------------------------------------------
void CInterface::SetCapture()
{
	CUi* ui = GetUi();
	if (ui)
	{
		ui->SetCapture(ui->GetRoot(), 0);
	}
}

// ----------------------------------------------------------------------------------
void CInterface::ReleaseCapture()
{
	CUi* ui = GetUi();
	if (ui)
	{
		ui->SetCapture(NULL, 0);
	}
}

// ----------------------------------------------------------------------------------
void CInterface::SetPlayerName(const char* playerName)
{
	m_playerName.clear();
	if ( playerName )
		m_playerName = playerName;

	if ( !m_playerName.empty() )
	{
		char tmp[1024];
		sprintf( tmp, "%s\\%s", m_savePath.c_str(), m_playerName.c_str() );
		CreateDirectory(tmp, NULL);			// 建立目錄
	}
}

// ----------------------------------------------------------------------------------
void CInterface::LoadPlayerData()
{
	// load data
	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		(*iter)->Load();
}

// ----------------------------------------------------------------------------------
void CInterface::SavePlayerData()
{
	// save data
	for (vector<CInterfaceBase*>::iterator iter = m_worldFrames.begin(); iter != m_worldFrames.end(); iter++)
		(*iter)->Save();
}

// ----------------------------------------------------------------------------------
bool CInterface::IsTocFile(const char* filename)
{
	if (filename)
	{
		int len = strlen(filename);
		if (len > 4 && strncmp(&filename[len-4], ".toc", 4) == 0)
			return true;
	}
	return false;
}

// ----------------------------------------------------------------------------------
void CInterface::LoadFiles(CUi* ui, const char* filename)
{
	if (IsTocFile(filename) && ui)
		ui->OpenTocFile(filename, m_resourcePath.c_str());
}

// ----------------------------------------------------------------------------------
void CInterface::LoadFolders(CUi* ui, const char* foldername)
{
	if ( foldername == NULL )
		return;

	WIN32_FIND_DATA fd;
	HANDLE h;
	string fullName(foldername);

	if ( fullName[fullName.size() - 1] == '\\' )
		fullName += "*.*";
	else
		fullName += "\\*.*";

	h = FindFirstFile( fullName.c_str(), &fd );
	if ( h != INVALID_HANDLE_VALUE )
	{
		do
		{
			string tmp(foldername);
			if ( tmp[tmp.size() - 1] != '\\' )
				tmp += "\\";
			tmp += fd.cFileName;
			//strlwr( (char*)tmp.c_str() );

			//目錄
			if ( ( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
			{
				if ( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
					LoadFolders( ui, tmp.c_str() );
			}
			//檔案
			else
				LoadFiles( ui, tmp.c_str() );

		} while( FindNextFile( h, &fd ) );
		FindClose( h );
	}
}

// --------------------------------------------------------------------------------------
void CInterface::CreateUiLogin(int width, int height)
{
	UI_SAFE_DELETE(m_uiLogin);
	m_uiLogin = new CUi;
	if (m_uiLogin)
	{
		m_uiLogin->SetScreenSize(CUiSize((float)width, (float)height));
	}
}

// --------------------------------------------------------------------------------------
void CInterface::CreateUiWorld(int width, int height)
{
	UI_SAFE_DELETE(m_uiWorld);
	m_uiWorld = new CUi;
	if (m_uiWorld)
	{		
		m_uiWorld->SetScreenSize(CUiSize((float)width, (float)height));
	}
}

// --------------------------------------------------------------------------------------
int	LuaFunc_GetGlobal (lua_State *L)
{
	lua_getglobal(L, luaL_checkstring(L, 1));
	return 1;
}

// ----------------------------------------------------------------------------------
int LuaFunc_ErrorOutput(lua_State* L)
{
	switch(lua_type(L, 1))
	{
	case LUA_TTABLE:
		{
			CUiLayout* layout = CUiLuaLayout::CheckLayoutTable(L, 1);
		} break;

	case LUA_TSTRING:
		{
			UiOuputError( luaL_checkstring(L, 1) );
		} break;
	}	
	return 0;
}

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

// ----------------------------------------------------------------------------------
int	LuaFunc_RunScript(lua_State* L)
{	
	if ( lua_dostring(L, luaL_checkstring(L, 1)) != 0 )
	{
		const char* err = lua_tostring(L, -1);
		lua_pop(L, 1);
		UiOuputError(err);
	}
	return 0;
}