#include "../../netwaker_member/NetWakerClientInc.h"
#include "../mainproc/GameMain.h"
#include "ChatFrame.h"

CChatFrame*						g_pChatFrame = NULL;

int LuaFunc_GetChatWindowInfo(lua_State* L);
int LuaFunc_GetChatWindowMessages(lua_State* L);
int	LuaFunc_GetChatWindowChannels(lua_State* L);
int LuaFunc_CreateChannel(lua_State* L);
int LuaFunc_JoinChannel(lua_State* L);
int LuaFunc_LeaveChannel(lua_State* L);
int LuaFunc_GetChannelName(lua_State* L);
int	LuaFunc_GetChannelList(lua_State* L);
int	LuaFunc_SetChatWindowShown(lua_State* L);
int LuaFunc_SetChatWindowName(lua_State* L);
int LuaFunc_SetChatWindowColor(lua_State* L);
int LuaFunc_SetChatWindowAlpha(lua_State* L);
int LuaFunc_SetChatWindowLocked(lua_State* L);
int LuaFunc_SetChatWindowDocked(lua_State* L);
int LuaFunc_AddChatWindowMessages(lua_State* L);
int LuaFunc_RemoveChatWindowMessages(lua_State* L);
int	LuaFunc_AddChatWindowChannel(lua_State* L);
int	LuaFunc_RemoveChatWindowChannel(lua_State* L);

// ----------------------------------------------------------------------------
CChatFrame::CChatFrame(CInterface* object)
	: CInterfaceBase(object)
{
	g_pChatFrame = this;

	m_channel.clear();
	for ( int i = 0; i < NUM_MAX_CHAT_WINDOWS; i++ )
	{
		m_windowInfo[i].typeList.clear();
		m_windowInfo[i].channelList.clear();
		m_windowInfo[i].name.clear();
		m_windowInfo[i].isLocked = true;
		m_windowInfo[i].isVisible = false;
		m_windowInfo[i].docked = 0;
		m_windowInfo[i].fontSize = 14;
		m_windowInfo[i].color.m_a = 0.3f;
		m_windowInfo[i].color.m_r = 0.3f;
		m_windowInfo[i].color.m_g = 0.3f;
		m_windowInfo[i].color.m_b = 0.3f;

		// Default Chat Window
		switch (i)
		{
		case 0:			
			m_windowInfo[i].typeList.push_back(eChatGroup_System);
			m_windowInfo[i].typeList.push_back(eChatGroup_Say);
			m_windowInfo[i].typeList.push_back(eChatGroup_Yell);
			m_windowInfo[i].typeList.push_back(eChatGroup_Whisper);
			m_windowInfo[i].typeList.push_back(eChatGroup_LFG);
			m_windowInfo[i].typeList.push_back(eChatGroup_Sale);
			m_windowInfo[i].typeList.push_back(eChatGroup_Loot);
			m_windowInfo[i].isVisible	= true;
			m_windowInfo[i].docked		= i+1;
			break;

		case 1:
			m_windowInfo[i].typeList.push_back(eChatGroup_Combat);
			m_windowInfo[i].isVisible	= true;
			m_windowInfo[i].docked		= i+1;
			break;

		case 2:
			m_windowInfo[i].typeList.push_back(eChatGroup_Say);
			m_windowInfo[i].typeList.push_back(eChatGroup_Whisper);
			m_windowInfo[i].typeList.push_back(eChatGroup_Party);
			m_windowInfo[i].typeList.push_back(eChatGroup_Raid);
			m_windowInfo[i].typeList.push_back(eChatGroup_LFG);
			m_windowInfo[i].isVisible	= true;
			m_windowInfo[i].docked		= i+1;
			break;

		case 3:
			m_windowInfo[i].typeList.push_back(eChatGroup_Say);
			m_windowInfo[i].typeList.push_back(eChatGroup_Whisper);
			m_windowInfo[i].typeList.push_back(eChatGroup_Guild);
			m_windowInfo[i].isVisible	= true;
			m_windowInfo[i].docked		= i+1;
			break;

		case 4:
			m_windowInfo[i].typeList.push_back(eChatGroup_Say);
			m_windowInfo[i].typeList.push_back(eChatGroup_Whisper);
			m_windowInfo[i].typeList.push_back(eChatGroup_Sale);
			m_windowInfo[i].isVisible	= true;
			m_windowInfo[i].docked		= i+1;
			break;
		}
	}
}

// ----------------------------------------------------------------------------
CChatFrame::~CChatFrame()
{
	g_pChatFrame = NULL;
}

// ----------------------------------------------------------------------------
void CChatFrame::RegisterFunc()
{
	lua_State* L = GetLuaStateWorld();
	if (L)
	{
		lua_register( L, "GetChatWindowInfo",			LuaFunc_GetChatWindowInfo );
		lua_register( L, "GetChatWindowMessages",		LuaFunc_GetChatWindowMessages );
		lua_register( L, "GetChatWindowChannels",		LuaFunc_GetChatWindowChannels );
		lua_register( L, "CreateChannel",				LuaFunc_CreateChannel );
		lua_register( L, "JoinChannel",					LuaFunc_JoinChannel );
		lua_register( L, "LeaveChannel",				LuaFunc_LeaveChannel );
		lua_register( L, "GetChannelName",				LuaFunc_GetChannelName );
		lua_register( L, "GetChannelList",				LuaFunc_GetChannelList );
		lua_register( L, "SetChatWindowShown",			LuaFunc_SetChatWindowShown );
		lua_register( L, "SetChatWindowName",			LuaFunc_SetChatWindowName );
		lua_register( L, "SetChatWindowColor",			LuaFunc_SetChatWindowColor );
		lua_register( L, "SetChatWindowAlpha",			LuaFunc_SetChatWindowAlpha );
		lua_register( L, "SetChatWindowLocked",			LuaFunc_SetChatWindowLocked );
		lua_register( L, "SetChatWindowDocked",			LuaFunc_SetChatWindowDocked );
		lua_register( L, "AddChatWindowMessages",		LuaFunc_AddChatWindowMessages );
		lua_register( L, "RemoveChatWindowMessages",	LuaFunc_RemoveChatWindowMessages );
		lua_register( L, "AddChatWindowChannel",		LuaFunc_AddChatWindowChannel );
		lua_register( L, "RemoveChatWindowChannel",		LuaFunc_RemoveChatWindowChannel );
	}
}

// ----------------------------------------------------------------------------
void CChatFrame::BuildFrames()
{
	SendWorldEvent(UIEVENT_UPDATE_CHAT_FRAMES);
}

// ----------------------------------------------------------------------------
// type CHAT_MSG_SYSTEM, CHAT_MSG_SAY.. 
void CChatFrame::SendMsgEvent(const char* type, const char* msg, const char* name)
{
	lua_State* L = GetLuaStateWorld();
	if ( L == NULL )
		return;

	// arg1
	lua_pushstring(L, msg);
	lua_setglobal(L, "arg1");

	// arg2	
	lua_pushstring(L, name);
	lua_setglobal(L, "arg2");

	SendWorldEvent(type);
}

// ----------------------------------------------------------------------------
void CChatFrame::AddMessage(int channel, const char* text)
{
	SendMsgEvent( CHAT_MSG_SYSTEM, text, "" );
}

// ----------------------------------------------------------------------------
ChatWindowInfo*	CChatFrame::GetChatWindowInfo(int id)
{
	if ( (unsigned int)id < NUM_MAX_CHAT_WINDOWS )
	{
		return &m_windowInfo[id];
	}
	return NULL;
}
// ----------------------------------------------------------------------------
int	CChatFrame::JoinChannelByName(const char* name, const char* password, bool isCreate)
{
	if ( name == NULL )
		name = "";
	if ( password == NULL )
		password = "";

	// 檢查名稱是否存在
	for ( map<int, string>::iterator iter = m_channel.begin(); iter != m_channel.end(); iter++ )
	{
		if ( strcmp((iter->second).c_str(), name) == 0 )
			return 0;
	}

	// 取得可用的頻道編號
	int channel = 1;
	while ( m_channel.find(channel) != m_channel.end() )
	{
		channel++;
		if ( channel > 9 )
			return 0;
	}

	m_channel.insert( make_pair(channel, name) );
	if ( isCreate )
		NetCli_Channel::S_CreateChannel( name, password );			// 送出封包
	else
		NetCli_Channel::S_JoinChannel( name, password );			// 送出封包

	return channel;
}

// ----------------------------------------------------------------------------
int CChatFrame::LeaveChannelByID(int id)
{
	map<int, string>::iterator iter = m_channel.find(id);
	if ( iter != m_channel.end() )
	{
		lua_State* L = GetLuaStateWorld();

		// 通知事件
		if ( L )
		{
			lua_pushnumber(L, id);
			lua_setglobal(L, "arg1");
			g_pChatFrame->SendWorldEvent(UIEVENT_CHAT_MSG_CHANNEL_LEAVE);
		}

		int channelID = NetCli_ChannelChild::GetChannelID( iter->second.c_str() );
		if ( channelID > 0 )
			NetCli_Channel::S_LeaveChannel( EM_GroupObjectType_PlayerChannel, channelID );

		m_channel.erase( iter );
		return id;
	}
	return 0;
}

// ----------------------------------------------------------------------------
int	CChatFrame::LeaveChannelByName(const char* name)
{
	for ( map<int, string>::iterator iter = m_channel.begin(); iter != m_channel.end(); iter++ )
	{
		if ( strcmp((iter->second).c_str(), name) == 0 )
			return LeaveChannelByID(iter->first);
	}
	return 0;
}

// ----------------------------------------------------------------------------
const char* CChatFrame::GetChannelName(int id)
{
	map<int, string>::iterator iter = m_channel.find(id);
	if ( iter != m_channel.end() )
		return iter->second.c_str();
	return "";
}

// ----------------------------------------------------------------------------
int	CChatFrame::GetChannelID(const char* name)
{
	if ( name == NULL )
		name = "";

	for ( map<int, string>::iterator iter = m_channel.begin(); iter != m_channel.end(); iter++ )
	{
		if ( strcmp(name, iter->second.c_str()) == 0 )
			return iter->first;
	}
	return 0;
}

// ----------------------------------------------------------------------------
bool CChatFrame::SendChannelMsg(int id, const char* playerName, const char* msg)
{
	map<int, string>::iterator iter = m_channel.find(id);
	if ( iter != m_channel.end() )
	{
		int channelID = NetCli_ChannelChild::GetChannelID( iter->second.c_str() );
		if ( channelID != -1 )
		{
			NetCli_Talk::Channel(EM_GroupObjectType_PlayerChannel, channelID, (char*)playerName, (char*)msg );
			return true;
		}
	}
	return false;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetChatWindowInfo(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{		
		lua_pushstring(L, info->name.c_str() );
		lua_pushnumber(L, info->fontSize );		
		lua_pushnumber(L, info->color.m_r );
		lua_pushnumber(L, info->color.m_g );
		lua_pushnumber(L, info->color.m_b );
		lua_pushnumber(L, info->color.m_a );
		lua_pushboolean(L, info->isVisible);
		lua_pushboolean(L, info->isLocked);
		if ( info->docked > 0 )
			lua_pushnumber(L, info->docked);
		else
			lua_pushboolean(L, 0);
		return 9;
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetChatWindowMessages(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) - 1);
	int size = 0;
	if ( info )
	{
		size = info->typeList.size();
		for ( int i = 0; i < size; i++ )
		{
			lua_pushstring(L, info->GetTypeListText(info->typeList[i]));
		}
	}
	return size;
}

// ----------------------------------------------------------------------------
int	LuaFunc_GetChatWindowChannels(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) - 1);
	int size = 0;
	if ( info )
	{
		for ( set<int>::iterator iter = info->channelList.begin(); iter != info->channelList.end(); iter++ )
		{
			lua_pushnumber(L, *iter);
			lua_pushstring(L, g_pChatFrame->GetChannelName(*iter));
			size += 2;
		}
	}
	return size;
}

// ----------------------------------------------------------------------------
// arg1 channel name
// arg2 channel password
int LuaFunc_CreateChannel(lua_State* L)
{
	const char* name = luaL_checkstring(L, 1);
	const char* password = "";

	if ( lua_isstring(L, 2) )
		password = lua_tostring(L, 2);

	lua_pushnumber(L, g_pChatFrame->JoinChannelByName(name, password, true));
	return 1;
}

// ----------------------------------------------------------------------------
// arg1 channel name
// arg2 channel password
int LuaFunc_JoinChannel(lua_State* L)
{
	const char* name = luaL_checkstring(L, 1);
	const char* password = "";

	if ( lua_isstring(L, 2) )
		password = lua_tostring(L, 2);

	lua_pushnumber(L, g_pChatFrame->JoinChannelByName(name, password, false));
	return 1;
}

// ----------------------------------------------------------------------------
int LuaFunc_LeaveChannel(lua_State* L)
{
	const char* name = luaL_checkstring(L, 1);
	if ( strlen(name) == 1 && *name >= 0 && *name <= 9 )
		g_pChatFrame->LeaveChannelByID(atoi(name));	
	else
		g_pChatFrame->LeaveChannelByName(name);
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_GetChannelName(lua_State* L)
{
	int channel = luaL_checkint(L, 1);
	lua_pushstring(L, g_pChatFrame->GetChannelName(channel));
	return 1;
}

// ----------------------------------------------------------------------------
int	LuaFunc_GetChannelList(lua_State* L)
{
	int size = 0;
	map<int, string>& channelList = g_pChatFrame->GetChannelList();
	for ( map<int, string>::iterator iter = channelList.begin(); iter != channelList.end(); iter++ )
	{
		lua_pushnumber(L, iter->first);
		lua_pushstring(L, iter->second.c_str());
		size++;
	}
	return size * 2;
}

// ----------------------------------------------------------------------------
int LuaFunc_SetChatWindowName(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		info->name = luaL_checkstring(L, 2);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_SetChatWindowColor(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		info->color.m_r = (float)luaL_checknumber(L, 2);
		info->color.m_g = (float)luaL_checknumber(L, 3);
		info->color.m_b = (float)luaL_checknumber(L, 4);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_SetChatWindowAlpha(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		info->color.m_a = (float)luaL_checknumber(L, 2);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int	LuaFunc_SetChatWindowShown(lua_State* L)
{
	int id = luaL_checkint(L, 1) -1;
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		if ( lua_isboolean(L, 2) && lua_toboolean(L, 2) )
			info->isVisible = true;
		else
			info->isVisible = false;
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_SetChatWindowLocked(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		if ( lua_isboolean(L, 2) && lua_toboolean(L, 2) )
			info->isLocked = true;
		else
			info->isLocked = false;
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_SetChatWindowDocked(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		switch ( lua_type(L, 2) )
		{
		case LUA_TNUMBER:
			info->docked = (int)lua_tonumber(L, 2);
			break;

		default:
			info->docked = 0;
			break;
		}		
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_AddChatWindowMessages(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		int typeNum = info->GetTypeListNum(luaL_checkstring(L, 2));
		if ( typeNum != -1 )
			info->typeList.push_back(typeNum);
	}
	return 0;
}

// ----------------------------------------------------------------------------
int LuaFunc_RemoveChatWindowMessages(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	if ( info )
	{
		int typeNum = info->GetTypeListNum(luaL_checkstring(L, 2));
		if ( typeNum != -1 )
		{
			for ( vector<int>::iterator iter = info->typeList.begin(); iter != info->typeList.end(); iter++ )
			{
				if ( *iter == typeNum )
				{
					info->typeList.erase(iter);
					break;
				}
			}
		}
	}
	return 0;
}

// ----------------------------------------------------------------------------
int	LuaFunc_AddChatWindowChannel(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	int channel = 0;
	if ( info )
	{
		if ( (channel = g_pChatFrame->GetChannelID(luaL_checkstring(L, 2))) > 0 )
		{
			if ( info->channelList.find(channel) != info->channelList.end() )
				channel = 0;
			else
				info->channelList.insert(channel);
		}
	}
	lua_pushnumber(L, channel);
	return 1;
}

// ----------------------------------------------------------------------------
int	LuaFunc_RemoveChatWindowChannel(lua_State* L)
{
	ChatWindowInfo* info = g_pChatFrame->GetChatWindowInfo(luaL_checkint(L, 1) -1);
	int channel = 0;
	if ( info )
	{
		if ( (channel = g_pChatFrame->GetChannelID(luaL_checkstring(L, 2))) > 0 )
		{
			if ( info->channelList.find(channel) != info->channelList.end() )
				info->channelList.erase(channel);
			else
				channel = 0;
		}
	}
	lua_pushnumber(L, channel);
	return 1;
}