#include "stdafx.h"
#include "GuildManager.h"
#include "GameResourceManager.h"
#include "ChatManager.h"
#include "GameUIManager.h"
#include "ObjectManager.h"
#include "Hero.h"
#include "UIMsgboxEvent.h"
#include "Npc_Common.h"
#include "GuildWindow.h"
#include "ResourceManager.h"
#include "SendNoteWindow.h"

#include "FileSystem.h"
#include "MemFile.h"

cGuildManager* cGuildManager::mpSingleton = 0;

cGuildManager::cGuildManager()
: mConnectCount(0)
, mTempNpcIndex(0)
, mTempCutPlayerIdx(0)
{
	assert( mpSingleton == 0 && "bad singleton!" );
	mpSingleton = this;

	::memset( &mGuildInfo, 0, sizeof(mGuildInfo) );
	::memset( &mMarkBuffer, 0, sizeof(mMarkBuffer) );
}

cGuildManager::~cGuildManager()
{
	cGuildUserMap::cIterator i = mGuildUserMap.Begin();
	cGuildUserMap::cIterator end = mGuildUserMap.End();
	for( ; i != end; ++i )
	{
		sGuildUserInfo* p = (sGuildUserInfo*)(i->mSecond);
		SAFE_DELETE( p );
	}
	mGuildUserMap.Clear();

	///
	mGuildMarkMap.Clear();

	/// 
	mRequestMarkMap.Clear();

	///
	mpSingleton = 0;
}

void cGuildManager::Close()
{
	Clear();
	ClearUI();
}

void cGuildManager::Clear()
{
	::memset( &mGuildInfo, 0, sizeof(mGuildInfo) );
	mConnectCount = 0;
	
	/// 
	cGuildUserMap::cIterator i = mGuildUserMap.Begin();
	cGuildUserMap::cIterator end = mGuildUserMap.End();
	for( ; i != end; ++i )
	{
		sGuildUserInfo* p = (sGuildUserInfo*)(i->mSecond);
		SAFE_DELETE( p );
	}
	mGuildUserMap.Clear();

	ClearTempData();

	mTempCutPlayerIdx = 0;
}

void cGuildManager::ClearUI()
{
	cGuildWindow* guildWindow = GAMEUI->GetGuildWindow();
	if( guildWindow )
		guildWindow->Clear();
}

void cGuildManager::ClearTempData()
{
	mTempName.Clear();

	mTempNpcIndex = 0;
}

void cGuildManager::ResGuildCreate( MSG_RES_NPC_GUILD_CREATE* pmsg )
{
	cStringT str;

	switch( pmsg->ErrorCode )
	{
	case ERROR_NPC_GUILD_CREATE_SUCESS:			// 성공
		str.Format( GAMERESOURCEMAN->GetGameText( 1200 ), (LPCTSTR)mTempName.Cstr() );
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			(LPCTSTR)str.Cstr(),
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	

		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, (LPCTSTR)str.Cstr() );
		break;
	case ERROR_NPC_GUILD_CREATE_FAIL:			// 실패
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 1201 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	
		break;
	case ERROR_NPC_GUILD_CREATE_CONDITION:		// 실패 - 가입조건 안됨
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 1232 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	
		break;
	case ERROR_NPC_GUILD_CREATE_ALREADY:		// 실패 - 이미 길드 가입중
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 1202 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	
		break;
	case ERROR_NPC_GUILD_CREATE_ERRORNAME:		// 실패 - 길드명 없거나 12자 넘음
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 1203 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	
		break;
	case ERROR_NPC_GUILD_CREATE_EXISTNAME:		// 실패 - 길드명 중복
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 1204 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);	
		break;
	case ERROR_NPC_GUILD_CREATE_NPC:	// 실패 - npc인증
		UIMAN->CreateModal(	eStage_Game,
			eMBEVENT_NONE, 
			GAMERESOURCEMAN->GetGameText( 420 ),	// 
			GAMERESOURCEMAN->GetGameText( 301 ),	// 알림
			eSKIN_OK
			);
		break;
	}

	ClearTempData();
}

void cGuildManager::NetworkMsgParser( char* msg )
{
	MSGROOT* tempMsg = (MSGROOT*)msg;

	cStringT str;
	switch( tempMsg->Protocol )
	{
	case NM_GUILD_LIST_SYN:
		{
			MSG_SYN_GUILD_LIST* pmsg = (MSG_SYN_GUILD_LIST*)msg;

			/// 초기화
			Clear();

			/// 세팅
			mGuildInfo = pmsg->data;

			sGuildUserInfo* user = pmsg->table;
			for( long i = 0; i < pmsg->rowCount; ++i, ++user )
			{
				AddGuildUser( user );
			}

			sGuildUserInfo* info = (sGuildUserInfo*)mGuildUserMap.GetAt( HERO->GetObjectID() );
			if( info )
			{
				/// 기본으로 채널 세팅
				info->channelNum = HERO->GetChannelNum();
				info->mapnum	 = (short)HERO->GetMapNum();
				HERO->SetGuild( mGuildInfo.idx, mGuildInfo.name, info->position, mGuildInfo.markIndex );
			}

			/// UI 갱신
			UpdateInfoSheet();
			UpdateNotice();
			UpdateGuildMark();
		}
		break;
	case NM_GUILD_CREATEDATA_RES:
		{	
			/// 길드 생성
			MSG_RES_GUILD_CREATEDATA* pmsg = (MSG_RES_GUILD_CREATEDATA*)msg;

			/// 초기화
			Clear();
			ClearUI();

			/// 1. 길드 데이터 세팅
			mGuildInfo.idx = pmsg->idx;
			mGuildInfo.masterIndex = HERO->GetObjectID();
			mGuildInfo.position = eGUILD_MASTER;
			mGuildInfo.markIndex = 0;
			mConnectCount = 1;
			::Sstrncpy( mGuildInfo.name, MAX_GUILDNAME_BUFFER_SIZE, pmsg->name, MAX_GUILDNAME_SIZE );
			::Sstrncpy( mGuildInfo.masterName, MAX_NAME_BUFFER_SIZE, HERO->GetName(), MAX_NAME_SIZE );

			/// 2. 유저리스트 세팅
			sGuildUserInfo* userInfo = new sGuildUserInfo;
			userInfo->characterIdx = HERO->GetObjectID();
			userInfo->level = HERO->GetLevel();
			userInfo->job = HERO->GetJob();
			userInfo->mapnum = (short)HERO->GetMapNum();
			userInfo->position = eGUILD_MASTER;
			userInfo->channelNum = HERO->GetChannelNum();
			::Sstrncpy( userInfo->name, MAX_NAME_BUFFER_SIZE, HERO->GetName(), MAX_NAME_SIZE );

			if( mGuildUserMap.Insert( userInfo->characterIdx, userInfo ) == false )
			{
				assert( 0 && "failed to insert guild user" );
			}

			/// UI 세팅
			UpdateInfoSheet();
			UpdateNotice();
			
			/// 
			HERO->SetGuild( mGuildInfo.idx, mGuildInfo.name, mGuildInfo.position, mGuildInfo.markIndex );
		}
		break;
	case NM_GUILD_ADD_RES:
		{
			// 길드초대 결과 ( 취소가능하게 해주어야함 )
			MSG_RES_GUILD_ADD* pmsg = (MSG_RES_GUILD_ADD*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_ADD_SUCCESS:		// 성공 - 길드 신청 성공
				{
					cStringT str;
					str.Format( GAMERESOURCEMAN->GetGameText( 1216 ), (LPCTSTR)mTempAddName.Cstr() );
					CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, (LPCTSTR)str.Cstr() );
				}
				break;
			case ERROR_GUILD_ADD_FAIL:			// 실패
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1206 ) );
				break;	
			case ERROR_GUILD_ADD_REQUEST:		// 실패 - 이미 신청중임
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1207 ) );
				break;
			case ERROR_GUILD_ADD_NOTEXIST:		// 실패 - 상대가 존재하지 않음
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1208 ) );
				break;
			case ERROR_GUILD_ADD_HAVEGUILD:		// 실패 - 상대가 이미 길드 가입중
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1209 ) );
				break;
			case ERROR_GUILD_ADD_MAXGUILD:		// 실패 - 길드 인원 제한
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1210 ) );
				break;
			case ERROR_GUILD_ADD_REFUSE:		// 실패 - 상대방 가입 거절
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1218 ) );
				break;
			}

			mTempAddName.Clear();
		}
		break;
	case NM_GUILD_ADD_SYN:
		{
			/// 다른 유저로부터 길드초대 받음
			MSG_SYN_GUILD_ADD* pmsg = (MSG_SYN_GUILD_ADD*)msg;
			
			str.Format( GAMERESOURCEMAN->GetGameText( 1215 ), pmsg->name, pmsg->guildName );
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_GUILD_ADD, 
								(LPCTSTR)str.Cstr(),					// 길드요청 메시지
								GAMERESOURCEMAN->GetGameText( 1214 ),	// 길드 요청
								eSKIN_YESNO
								, 0, GUILD_WAIT_TIME, false, false );
		}
		break;
	case NM_GUILD_REPLY_RES:
		{
			/// 길드초대 답변에 대한 결과
			MSG_RES_GUILD_REPLY* pmsg = (MSG_RES_GUILD_REPLY*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_ADDREPLY_SUCCESS:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1211 ) );
				break;
			case ERROR_GUILD_ADDREPLY_FAIL:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1212 ) );
				break;
			case ERROR_GUILD_ADDREPLY_REFUSE:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1213 ) );
				break;
			}
		}
		break;
	case NM_GUILD_USERADD_SYN:
		{
			/// 추가된 길드유저 정보
			MSG_SYN_GUILD_USERADD* pmsg = (MSG_SYN_GUILD_USERADD*)msg;

			// 길드 유저 추가
			AddGuildUser( &pmsg->user );

			// UI 갱신
			UpdateInfoSheetByUser();

			//
			str.Format( GAMERESOURCEMAN->GetGameText( 1217 ), &pmsg->user.name );
			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, str.Cstr() );
		}
		break;
	case NM_GUILD_OUT_RES:
		{
			/// 길드 탈퇴 
			MSG_RES_GUILD_OUT* pmsg = (MSG_RES_GUILD_OUT*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_OUT_SUCCESS:
				{
					// 탈퇴 성공
					Clear();
					ClearUI();

					HERO->SetGuild( 0, _T(""), eGUILD_NONE, 0 );

					CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1219 ) );
				}
				break;
			case ERROR_GUILD_OUT_FAIL:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1220 ) );
				break;
			case ERROR_GUILD_OUT_MASTER:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1221 ) );
				break;
			}
		}
		break;
	case NM_GUILD_OUT_SYN:
		{
			/// 길드 탈퇴 
			MSG_SYN_GUILD_OUT* pmsg = (MSG_SYN_GUILD_OUT*)msg;

			cGuildUserMap::cIterator i = mGuildUserMap.Find( pmsg->characterIdx );
			if( i != mGuildUserMap.End() )
			{
				sGuildUserInfo* user = (sGuildUserInfo*)(i->mSecond);
				
				// 탈퇴 알림
				str.Format( GAMERESOURCEMAN->GetGameText( 1222 ), user->name );
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, (LPCTSTR)str.Cstr() );

				// 삭제
				SAFE_DELETE( user );
				mGuildUserMap.Erase( i );

				// UI 갱신
				UpdateInfoSheetByUser();
			}
		}
		break;
	case NM_GUILD_CUT_RES:
		{
			/// 길드원 추방요청 결과
			MSG_RES_GUILD_CUT* pmsg = (MSG_RES_GUILD_CUT*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_CUT_SUCCESS:
				{
					/// 추방당한 유저에게 쪽지보내기
					cSendNoteWindow* win = GAMEUI->GetSendNoteWindow();
					if( win )
					{
						cGuildUserMap::cIterator i = mGuildUserMap.Find( mTempCutPlayerIdx );
						if( i != mGuildUserMap.End() )
						{
							sGuildUserInfo* user = (sGuildUserInfo*)(i->mSecond);
							win->SendNoteBySystem( user->name, GAMERESOURCEMAN->GetGameText( 1257 ) );
						}
					}
				}
				break;
			case ERROR_GUILD_CUT_FAIL:		// 실패
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1223 ) );
				break;
			case ERROR_GUILD_CUT_MASTER:	// 실패 - 길드장만 추방가능
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1224 ) );
				break;
			}

			mTempCutPlayerIdx = 0;
		}
		break;
	case NM_GUILD_CUT_SYN:
		{
			/// 자기자신이 추방됨
			Clear();
			ClearUI();

			HERO->SetGuild( 0, _T(""), eGUILD_NONE, 0 );

			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1225 ) );
		}
		break;
	case NM_GUILD_USERCUT_SYN:
		{
			/// 길드원이 추방됨
			MSG_SYN_GUILD_USERCUT* pmsg = (MSG_SYN_GUILD_USERCUT*)msg;

			cGuildUserMap::cIterator i = mGuildUserMap.Find( pmsg->characterIdx );
			if( i != mGuildUserMap.End() )
			{
				sGuildUserInfo* user = (sGuildUserInfo*)(i->mSecond);

				// 탈퇴 알림
				str.Format( GAMERESOURCEMAN->GetGameText( 1226 ), user->name );
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, (LPCTSTR)str.Cstr() );

				// 삭제
				SAFE_DELETE( user );
				mGuildUserMap.Erase( i );

				// UI 갱신
				UpdateInfoSheetByUser();
			}
		}
		break;
	case NM_GUILD_DELETE_RES:
		{
			MSG_RES_GUILD_DELETE* pmsg = (MSG_RES_GUILD_DELETE*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_DELETE_SUCCESS:
				{
					// 길드해체 성공
					Clear();
					ClearUI();

					HERO->SetGuild( 0, _T(""), eGUILD_NONE, 0 );

					CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1230 ) );
				}
				break;
			case ERROR_GUILD_DELETE_FAIL:
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1229 ) );
				break;
			case ERROR_GUILD_DELETE_MASTER:		// 실패 - 길드장만 해체 가능
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1227 ) );
				break;
			case ERROR_GUILD_DELETE_USEREXIST:	// 실패 - 길드유저가 남아있음
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1228 ) );
				break;
			}
		}
		break;
	case NM_GUILD_UPDATE_SYN:
		{
			/// 시간에 의한 길드 정보 갱신
			MSG_SYN_GUILD_UPDATE* pmsg = (MSG_SYN_GUILD_UPDATE*)msg;
			
			// 갱신
			sGuildUserUpdate* data = pmsg->table;
			for( long i = 0; i < pmsg->rowCount; ++i, ++data )
			{
				sGuildUserInfo* user = (sGuildUserInfo*)mGuildUserMap.GetAt( data->characterIdx );
				if( user )
				{
					user->level  = data->level;
					user->job	 = data->job;
					user->mapnum = data->mapnum;
					user->channelNum = data->channelNum;
				}
			}
		
			/// UI 갱신
            UpdateInfoSheetByUser();
		}
		break;
	case NM_GUILD_GIVEPOSITION_RES:
		{
			/// 직위변경 요청 결과
			MSG_RES_GUILD_GIVEPOSITION* pmsg = (MSG_RES_GUILD_GIVEPOSITION*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILD_GIVEPOSITION_SUCCESS:
				break;
			case ERROR_GUILD_GIVEPOSITION_FAIL:			/// 실패
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1244 ) );
				break;
			case ERROR_GUILD_GIVEPOSITION_POSITION:		/// 권한
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1245 ) );
				break;
			}
		}
		break;
	case NM_GUILD_GIVEPOSITION_SYN:
		{
			/// 직위 변경됨
			MSG_SYN_GUILD_GIVEPOSITION* pmsg = (MSG_SYN_GUILD_GIVEPOSITION*)msg;

			/// 본인이 길드장인경우 
			if( pmsg->position == eGUILD_MASTER && HERO->GetObjectID() == mGuildInfo.masterIndex )
			{
				mGuildInfo.position = eGUILD_GENERAL;
			}
			else if( pmsg->characterIdx == HERO->GetObjectID() )
			{
				mGuildInfo.position = pmsg->position;
			}
	
			/// 길드 유저 리스트 갱신
			sGuildUserInfo* newInfo = (sGuildUserInfo*)mGuildUserMap.GetAt( pmsg->characterIdx );
			if( newInfo )
			{
				newInfo->position = pmsg->position;

				/// 새로운 길드장일 경우 추가 처리
				if( pmsg->position == eGUILD_MASTER )
				{
					/// 기존 길드장의 직위 변경
					sGuildUserInfo* userInfo = (sGuildUserInfo*)mGuildUserMap.GetAt( mGuildInfo.masterIndex );
					if( userInfo )
					{
						userInfo->position = eGUILD_GENERAL;
					}
					else
					{
						assert(0);
					}

					/// 새 길드장 정보 세팅
					mGuildInfo.masterIndex = pmsg->characterIdx;
					::Sstrncpy( mGuildInfo.masterName, MAX_NAME_BUFFER_SIZE, newInfo->name, MAX_NAME_SIZE );
				}

				/// 변경정보 알림
				str.Format( GAMERESOURCEMAN->GetGameText( 1246 ), newInfo->name, GetTextIndex( pmsg->position ) );
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, (LPCTSTR)str.Cstr() );
			}
			else
			{
				assert(0);
			}

			/// UI 세팅
			UpdateInfoSheet();
			UpdateGuildMark();
			UpdateNotice( false );

			///
			HERO->SetGuildPosition( mGuildInfo.position );
		}
		break;
	case NM_GUILD_NOTICE_RES:
		{
			MSG_RES_GUILD_NOTICE* pmsg = (MSG_RES_GUILD_NOTICE*)msg;

			if( pmsg->ErrorCode == ERROR_GUILD_NOTICE_FAIL )
			{
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1250 ) );
			}
		}
		break;
	case NM_GUILD_NOTICE_SYN:
		{
			MSG_SYN_GUILD_NOTICE* pmsg = (MSG_SYN_GUILD_NOTICE*)msg;

			/// 저장
			::Sstrncpy( mGuildInfo.notice, MAX_GUILD_NOTICE_BUFFER_SIZE, pmsg->notice, MAX_GUILD_NOTICE_SIZE );

			/// UI출력
			UpdateNotice();
		}
		break;
	case NM_GUILDMARK_UPDATE_RES:
		{
			/// 길드마크 변경 결과
			MSG_RES_GUILDMARK_UPDATE* pmsg = (MSG_RES_GUILDMARK_UPDATE*)msg;

			switch( pmsg->ErrorCode )
			{
			case ERROR_GUILDMARK_UPDATE_FAIL:			// 실패
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1252 ) );
				break;
			case ERROR_GUILDMARK_UPDATE_POSITION:		// 권한실패
				CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1253 ) );
				break;
			}
		}
		break;
	case NM_GUILDMARK_UPDATE_SYN:
		{
			/// 자신의 길드 마크 변경됨
			MSG_SYN_GUILDMARK_UPDATE* pmsg = (MSG_SYN_GUILDMARK_UPDATE*)msg;
			
			/// 저장
			mGuildInfo.markIndex = pmsg->markIndex;

			/// 길드 UI마크 갱신
			UpdateGuildMark();

			/// 해당 길드마크가 존재하는지 검사.
			HERO->ChangeGuildMark( pmsg->markIndex );

			/// 변경 알림
			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1254 ) );
		}
		break;
	case NM_GUILDMARK_SEND_RES:
		{
			MSG_RES_GUILDMARK_SEND* pmsg = (MSG_RES_GUILDMARK_SEND*)msg;

			/// 새로운 길드마크 정보 받음
			if( pmsg->ErrorCode == ERROR_GUILDMARK_SEND_SUCCESS )
			{
				/// 길드마크 받아서 새 파일로 생성
				cString str;
				str.Format( "./GuildMark/mark%d_%d.tga", pmsg->guildIndex, pmsg->markIndex );
				cFileToWrite* newfile = FILESYSTEM->OpenFileToWrite( str );
				if( newfile )
				{
					int writeLen = newfile->Write( pmsg->mark, MARK_SIZE );
					/*if( writeLen != MARK_SIZE )
					{
						assert(0);
					}*/
					newfile->Close();
					SAFE_DELETE( newfile );
				}

				/// 길드마크 관리자에 등록
				NiTexture* tex = LoadGuildMark( str );
				if( tex )
				{
					if( mGuildMarkMap.Insert( pmsg->markIndex, tex ) == false )
					{
						assert(0);
					}

					/// 길드마크 갱신
					OBJECTMANAGER->UpdateGuildMark( pmsg->guildIndex, pmsg->markIndex );

					/// 길드 UI에 등록
					if( pmsg->guildIndex == HERO->GetGuildIndex() )
					{
						cGuildWindow* win = GAMEUI->GetGuildWindow();
						if( win )
						{
							win->ChangeMark( tex );
						}
						else
						{
							assert(0);
						}
					}
				}
			}
			else
			{
				assert(0);
			}

			/// 요청 맵으로부터 삭제
			mRequestMarkMap.Erase( pmsg->guildIndex );
		}
		break;
	}
}

void cGuildManager::UpdateGuildMark()
{
	cGuildWindow* win = GAMEUI->GetGuildWindow();
	if( win )
	{
		/// 관리자에 있으면 찾아서 세팅
		NiTexture* tex = (NiTexture*)mGuildMarkMap.GetAt( mGuildInfo.markIndex );
		if( tex )
		{
			win->ChangeMark( tex );
		}
		else
		{
			/// 없으면 파일명으로 찾기
			cString str;
			str.Format( "./GuildMark/mark%d_%d.tga", mGuildInfo.idx, mGuildInfo.markIndex );
			tex = LoadGuildMark( str );
			if( tex )
			{
				if( mGuildMarkMap.Insert( mGuildInfo.markIndex, tex ) == false )
				{
					assert(0);
				}

				win->ChangeMark( tex );
			}
		}
	}
}

NiTexture* cGuildManager::CheckGuildMark( unsigned long guildIndex, unsigned long markIndex )
{
	/// 관리자에 있으면 찾아서 세팅
	NiTexture* tex = 0;

	tex = (NiTexture*)mGuildMarkMap.GetAt( markIndex );
	if( tex )
		return tex;

	/// 없으면 파일명으로 찾기
	cString str;
	str.Format( "./GuildMark/mark%d_%d.tga", guildIndex, markIndex );
	
	tex = LoadGuildMark( str );
	if( tex )
	{
		if( mGuildMarkMap.Insert( markIndex, tex ) == false )
		{
			assert(0);
		}
	}
	else
	{
		///
		cRequestMarkMap::cIterator i = mRequestMarkMap.Find( guildIndex );
		if( i == mRequestMarkMap.End() )
		{
			/// 파일로도 존재하지 않으면 서버에 요청
			MSG_REQ_GUILDMARK_SEND sendmsg;
			::memset( &sendmsg, 0, sizeof(sendmsg) );
			sendmsg.Category = NM_GUILD;
			sendmsg.Protocol = NM_GUILDMARK_SEND_REQ;
			sendmsg.guildIndex = guildIndex;
			NETWORK->SendNetworkMsg( (char*)&sendmsg, sizeof(sendmsg) );

			/// 요청 맵에 저장
			if( mRequestMarkMap.Insert( guildIndex, markIndex ) == false )
			{
				assert(0);
			}
		}
	}
	return tex;
}

void cGuildManager::AddGuildUser( sGuildUserInfo* user )
{
	sGuildUserInfo* userInfo = new sGuildUserInfo;

	/// 복사
	*userInfo = *user;

	if( mGuildUserMap.Insert( userInfo->characterIdx, userInfo ) == false )
	{
		assert( 0 && "failed to insert guild user" );
	}
}

void cGuildManager::SetTempData( LPCTSTR name, unsigned long npcIdx )
{
	mTempName = name;
	mTempNpcIndex = npcIdx;
}

/// 길드 생성 가능 검사
bool cGuildManager::CheckCreate( unsigned long npcIdx )
{
	// 1. 길드 가입검사
	if( HERO->GetGuildIndex() > 0 )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 1202 ),	
							GAMERESOURCEMAN->GetGameText( 1233 ),	// 길드 생성
							eSKIN_OK );

		UIMAN->HideNpcBack();
		return false;
	}

	// 2. 레벨 검사
	if( HERO->GetLevel() < GUILDLIMIT_LEVEL )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 1237 ),	
							GAMERESOURCEMAN->GetGameText( 1233 ),	// 길드 생성
							eSKIN_OK );

		UIMAN->HideNpcBack();
		return false;
	}

	// 3. 금액 검사
	if( HERO->GetMoney() < GUILDLIMIT_MONEY )
	{
		UIMAN->CreateModal(	eStage_Game,
							eMBEVENT_NONE, 
							GAMERESOURCEMAN->GetGameText( 1238 ),	
							GAMERESOURCEMAN->GetGameText( 1233 ),	// 길드 생성
							eSKIN_OK );

		UIMAN->HideNpcBack();
		return false;
	}
	return true;
}

/// 길드 생성 요청
bool cGuildManager::GuildCreate()
{
	if( HERO->GetGuildIndex() > 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1202 ) );
		return false;
	}

	// 길이 검사 
	if( mTempName.IsEmpty() )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1203 ) );
		return false;
	}

	// npc 인증실패
	if( mTempNpcIndex == 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 420 ) );
		return false;
	}

	MSG_REQ_NPC_GUILD_CREATE msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_NPC;
	msg.Protocol = NM_NPC_GUILD_CREATE_REQ;
	msg.npcIndex = mTempNpcIndex;
	::Sstrncpy( msg.name, MAX_GUILDNAME_BUFFER_SIZE, (LPCTSTR)mTempName.Cstr(), MAX_GUILDNAME_SIZE );

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
	return true;
}

/// 길드 초대 요청
void cGuildManager::GuildAdd( cStringT name )
{
	if( HERO->GetGuildIndex() == 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1205 ) );
		return;
	}

	if( name.IsEmpty() )
	{
		cBaseObject* pTarget = HERO->GetTargetObject();
		if( pTarget && pTarget->GetObjectType() == eOBJECTTYPE_PLAYER )
		{
			name = pTarget->GetName();
		}
		else
		{
			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 102 ) );
			return;
		}
	}

	/// 자기자신 초대불가
	if( ::_tcscmp( (LPCTSTR)name.Cstr(), HERO->GetName() ) == 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 142 ) );
		return;
	}

	///
	mTempAddName = name;

	///
	MSG_REQ_GUILD_ADD msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILD_ADD_REQ;
	::Sstrncpy( msg.name, MAX_NAME_BUFFER_SIZE, (LPCTSTR)name.Cstr(), MAX_NAME_SIZE );

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

/// 길드 탈퇴 요청
void cGuildManager::GuildOut()
{
	if( HERO->GetGuildPosition() == eGUILD_NONE )
	{
		assert(0);
		return;
	}
	if( HERO->GetGuildPosition() == eGUILD_MASTER )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1221 ) );
		return;
	}

	MSG_REQ_GUILD_OUT msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILD_OUT_REQ;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

/// 길드 추방 요청
void cGuildManager::GuildCut( unsigned long characterIdx )
{
	sGuildUserInfo* info = (sGuildUserInfo*)mGuildUserMap.GetAt( characterIdx );
	if( info != NULL )
	{
		mTempCutPlayerIdx = characterIdx;

		MSG_REQ_GUILD_CUT msg;
		::memset( &msg, 0, sizeof(msg) );
		msg.Category = NM_GUILD;
		msg.Protocol = NM_GUILD_CUT_REQ;
		msg.characterIdx = characterIdx;
		NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
	}
	else
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1224 ) );
	}
}

///
void cGuildManager::GuildDelete()
{
	// 길드원 남아있는지 검사
	if( mGuildUserMap.GetSize() > 1 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1228 ) );
		return;
	}

	MSG_REQ_GUILD_DELETE msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILD_DELETE_REQ;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

///
void cGuildManager::GuildGivePosition( unsigned long characterIdx, unsigned char position, unsigned char newPosition )
{
	if( HERO->GetGuildIndex() == 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1205 ) );
		return;
	}
	
	char heroPos = HERO->GetGuildPosition();
	if( !(heroPos == eGUILD_MASTER || heroPos == eGUILD_SUBMASTER) )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1245 ) );
		return;
	}
	
	/// 길드장이 아닌경우
	/// 해당 유저의 직위가 자신과 같거나 높을수 없다
	/// 변경할 직위가 자신과 같거나 높을수 없다
	if( heroPos != eGUILD_MASTER )
	{
		if( !(heroPos < position && heroPos < newPosition) )
		{
			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1245 ) );
			return;
		}
	}
	else if( heroPos == eGUILD_MASTER )
	{
		/// 해당유저가 길드장일수없음
		if( !(heroPos < position) )
		{
			CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1245 ) );
			assert(0);
			return;
		}
	}

	/// 요청
	MSG_REQ_GUILD_GIVEPOSITION msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILD_GIVEPOSITION_REQ;
	msg.characterIdx = characterIdx;
	msg.position = newPosition;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

void cGuildManager::GuildNotice( LPCTSTR notice )
{
	if( HERO->GetGuildIndex() == 0 )
	{
		CHATMANAGER->AddSystemMsg( eSYSTEM_NORMAL, GAMERESOURCEMAN->GetGameText( 1205 ) );
		return;
	}

	///
	MSG_REQ_GUILD_NOTICE msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILD_NOTICE_REQ;
	::Sstrncpy( msg.notice, MAX_GUILD_NOTICE_BUFFER_SIZE, notice, MAX_GUILD_NOTICE_SIZE );
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

void cGuildManager::GuildMarkUpdate()
{
	MSG_REQ_GUILDMARK_UPDATE msg;
	::memset( &msg, 0, sizeof(msg) );
	msg.Category = NM_GUILD;
	msg.Protocol = NM_GUILDMARK_UPDATE_REQ;
	memcpy( &msg.mark, &mMarkBuffer, MARK_SIZE );

	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );
}

bool GuildUserSort( const void *arg1, const void *arg2 )
{
	sGuildUserInfo* data1 = (sGuildUserInfo*)arg1;
	sGuildUserInfo* data2 = (sGuildUserInfo*)arg2;

	return (data2->position - data1->position > 0);
}

/// UI 세팅
void cGuildManager::UpdateInfoSheet()
{
	if( mGuildInfo.idx == 0 )
		return;

	typedef tList<void*> cSortList;
	cSortList list;

	cGuildWindow* guildWindow = GAMEUI->GetGuildWindow();
	if( guildWindow )
	{
		mConnectCount = 0;
		guildWindow->Clear();

		/// 길드 정보 세팅
		guildWindow->SetGuildName( mGuildInfo.name );
		guildWindow->SetMasterName( mGuildInfo.masterName );
		guildWindow->SetPosition( mGuildInfo.position );
		guildWindow->SetTotalCount( mGuildUserMap.GetSize() );

		/// 유저리스트 갱신
		cGuildUserMap::cIterator i = mGuildUserMap.Begin();
		cGuildUserMap::cIterator end = mGuildUserMap.End();
		for( ; i != end; ++i )
		{
			sGuildUserInfo* p = (sGuildUserInfo*)(i->mSecond);
			list.PushBack( p );
		}

		list.Sort( GuildUserSort );

		///
		cSortList::cIterator li = list.Begin();
		cSortList::cIterator lend = list.End();
		for( ; li != lend; ++li )
		{
			sGuildUserInfo* p = (sGuildUserInfo*)(*li);
			guildWindow->AddGuildPlayer( p );

			// 접속인수 계산
			if( p->channelNum > 0 )
				mConnectCount++;
		}

		guildWindow->SetConnectCount( mConnectCount );
	}
}

/// UI 세팅 - 길드원 가입/탈퇴에 따른 갱신
void cGuildManager::UpdateInfoSheetByUser()
{
	typedef tList<void*> cSortList;
	cSortList list;

	cGuildWindow* guildWindow = GAMEUI->GetGuildWindow();
	if( guildWindow )
	{
		mConnectCount = 0;

		guildWindow->SetTotalCount( mGuildUserMap.GetSize() );

		unsigned int selectrow = guildWindow->GetSelectRow();

		/// 유저리스트 갱신
		guildWindow->ClearList();
		cGuildUserMap::cIterator i = mGuildUserMap.Begin();
		cGuildUserMap::cIterator end = mGuildUserMap.End();
		for( ; i != end; ++i )
		{
			sGuildUserInfo* p = (sGuildUserInfo*)(i->mSecond);
			list.PushBack( p );
		}

		list.Sort( GuildUserSort );

		///
		cSortList::cIterator li = list.Begin();
		cSortList::cIterator lend = list.End();
		for( ; li != lend; ++li )
		{
			sGuildUserInfo* p = (sGuildUserInfo*)(*li);
			guildWindow->AddGuildPlayer( p );

			// 접속인수 계산
			if( p->channelNum > 0 )
				mConnectCount++;
		}

		//
		guildWindow->SetConnectCount( mConnectCount );
		guildWindow->SetSelectRow( selectrow );
	}
}

/// 길드 공지 갱신
void cGuildManager::UpdateNotice( bool sendChat )
{
	int len = ::_tcslen( mGuildInfo.notice );
	if( len > 0 )
	{
		if( sendChat == true )
		{
			cStringT str;
			str.Format( GAMERESOURCEMAN->GetGameText( 1251 ), mGuildInfo.notice );
			CHATMANAGER->AddChatMsg( (LPCTSTR)str.Cstr(), eCHAT_GUILD );
		}

		///
		cGuildWindow* win = GAMEUI->GetGuildWindow();
		if( win )
			win->UpdateGuildNotice( mGuildInfo.notice );
	}
}

/// 직위에 따른 텍스트 인덱스 
LPCTSTR cGuildManager::GetTextIndex( unsigned char position )
{
	unsigned int textIdx = 0;
	switch( position )
	{
	case eGUILD_NONE:		textIdx = 1299;		break;		/// 길드장
	case eGUILD_MASTER:		textIdx = 1300;		break;		/// 길드장
	case eGUILD_SUBMASTER:	textIdx = 1301;		break;		/// 부 길드장
	case eGUILD_ELDER:		textIdx = 1302;		break;		/// 장로
	case eGUILD_UPPERHOUSE:	textIdx = 1303;		break;		/// 상원 의원
	case eGUILD_LOWERHOUSE:	textIdx = 1304;		break;		/// 하원 의원
	case eGUILD_GENERAL:	textIdx = 1305;		break;		/// 일반
	default:		
		assert(0);		
		return 0;
	}

	return GAMERESOURCEMAN->GetGameText( textIdx );
}

/// 길드 마크 등록 ui 용 로딩
NiTexture* cGuildManager::LoadGuildMark( const cString& pathName, bool tempMark )
{
	cFileToRead* file = FILESYSTEM->OpenFileToRead( pathName );

	/// 1. 파일 유무 검사
	if( !file )
		return 0;

	/// 2. 빈파일 검사
	if( file->IsEmpty() == true )
		return 0;

	unsigned char ucharTemp = 0;
	short int sintTemp = 0;

	TARGAFILEHEADER header;
	::memset( &header, 0, sizeof(header) );

	file->Read( &ucharTemp, sizeof(unsigned char) );
	file->Read( &ucharTemp, sizeof(unsigned char) );
	file->Read( &header.imageTypeCode, sizeof(unsigned char) );
	file->Read( &sintTemp, sizeof(short int) );
	file->Read( &sintTemp, sizeof(short int) );
	file->Read( &ucharTemp, sizeof(unsigned char) );
	file->Read( &sintTemp, sizeof(short int) );
	file->Read( &sintTemp, sizeof(short int) );
	file->Read( &header.imageWidth, sizeof(short int) );
	file->Read( &header.imageHeight, sizeof(short int) );
	file->Read( &header.bitCount, sizeof(unsigned char) );
	file->Read( &header.imageDescriptor, sizeof(unsigned char) );

	/// 3. tga 이미지타입 검사 ( 2 : 무압축 RGB )
	if( header.imageTypeCode != 2 )
		return 0;

	/// 4. 파일 사이즈 검사
	if( !(header.imageWidth == 24 && header.imageHeight == 24) )
		return 0;

	/// 4. 파일 사이즈 검사 (제한 사이즈 검사)
	unsigned int len = file->GetSize();
	if( len > MARK_SIZE )
		return 0;

	int fileSize = header.imageWidth * header.imageHeight * (header.bitCount / 8) + MARK_HEADER_SIZE + TGA_EXTENSION;
	//if( fileSize != len )
	//	return 0;*/

	/// 길드마크 등록용 파일인지 검사
	if( tempMark == true )
	{
		/// 파일 전체 복사
		file->Seek( 0 );
		::memset( &mMarkBuffer, 0, sizeof(mMarkBuffer) );
		int readLen = file->Read( &mMarkBuffer, fileSize );
		/*if( readLen != MARK_SIZE )
		{
			assert(0);
			return 0;
		}*/
	}
	
	/// 텍스쳐 로딩
	file->Seek( 0 );
	NiTexture* tex = RESOURCEMAN->LoadGuildMark( pathName, file, tempMark );
	file->Close();

	SAFE_DELETE( file );
	return tex;
}
