#include "StdAfx.h"
#include "FriendWindow.h"
#include "UIMsgboxEvent.h"
#include "SendNoteWindow.h"
#include "FriendListbox.h"
#include "UIImage.h"
#include "UINodeData.h"
#include "ChatWindow.h"
#include "ChatManager.h"
#include "Button.h"

#include "CommonNetworkMsgStruct.h"
#include "GameUIManager.h"
#include "Protocol.h"
#include "Player_Common.h"
#include "Party_Common.h"
#include "PartyManager.h"
#include "ObjectManager.h"
#include "Hero.h"

cFriendWindow::cFriendWindow()
: mpFriendList(0)
, mParty(0)
, mAddFriend(0)
, mDelFriend(0)
, mWhisper(0)
{
	for( int i = 0; i < MAXPAGE_NUM; ++i )
		mpRadioNode[i] = 0;

	mCheckRect.Set( 0, 0, 0, 0 );
}

cFriendWindow::~cFriendWindow()
{
	if( mpFriendList )
		mpFriendList->Clear();

	///
	for( unsigned int i = 0; i < mFriendArr.GetSize(); ++i )
	{
		sFriendData* data = (sFriendData*)mFriendArr[i];
		SAFE_DELETE( data );
	}
	mFriendArr.Clear();

	///
	for( unsigned int i = 0; i < mImageArr.GetSize(); ++i )
	{
		cUIImage* pImage = (cUIImage*)mImageArr[i];
		SAFE_DELETE( pImage );
	}
	mImageArr.Clear();
}

///
void cFriendWindow::Clear()
{
	if( mpFriendList )
		mpFriendList->Clear();

	///
	for( unsigned int i = 0; i < mFriendArr.GetSize(); ++i )
	{
		sFriendData* data = (sFriendData*)mFriendArr[i];
		SAFE_DELETE( data );
	}
	mFriendArr.Clear();

	/// 버튼 설정 초기화
	if( mParty )
		mParty->SetEnabled( false );
	if( mDelFriend )
		mDelFriend->SetEnabled( false );
	if( mWhisper )
		mWhisper->SetEnabled( false );

	for( int i = 0 ; i < MAXPAGE_NUM; ++i )
	{
		if( mpRadioNode[i] )
			mpRadioNode[i]->Hide();
	}
}

void cFriendWindow::OnShow()
{
	/// 서버에 친구리스트 요청
	MSG_REQ_FRIEND_LIST msg;
	::memset( &msg, 0, sizeof( msg ) );
	msg.Category = NM_CHAT;
	msg.Protocol = NM_CHAT_FRIEND_LIST_REQ;
	NETWORK->SendNetworkMsg( (char*)&msg, sizeof(msg) );

	cUIWindow::OnShow();
}

/// 주의사항 : 
bool cFriendWindow::OnCreate( cUINodeProperty* pproperty )
{
	if( cUIWindow::OnCreate( pproperty ) == false )
		return false;

	mpFriendList = (cFriendListbox*)GetChild( eUIID_GAME_FRIEND_LISTBOX );
	mParty = (cButton*)GetChild( eUIID_GAME_FRIEND_PARTYBUTTON );
	mAddFriend = (cButton*)GetChild( eUIID_GAME_FRIEND_ADDFRIENDBUTTON );
	mDelFriend = (cButton*)GetChild( eUIID_GAME_FRIEND_DELETEFREINDBUTTON );
	mWhisper = (cButton*)GetChild( eUIID_GAME_FRIEND_WHISPERBUTTON );

	CHATMANAGER->SetFriendWindow( this );

	/// 버튼 초기화 설정
	if( mParty )
		mParty->SetEnabled( false );
	if( mDelFriend )
		mDelFriend->SetEnabled( false );
	if( mWhisper )
		mWhisper->SetEnabled( false );

	/// 사용이미지 생성
	CreateImage( "Human_M" );
	CreateImage( "Beast_M" );
	CreateImage( "Elf_M" );
	CreateImage( "Human_W" );
	CreateImage( "Beast_W" );
	CreateImage( "Elf_W" );

	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
	{
		assert(0);
		return false;
	}

	/// 정렬영역
	cUINodeSkin* pRectSkin = pSkin->GetNodeSkin( "Friend_ButtonRect" );
	if( pRectSkin )
	{
		mCheckRect.mLeft = pRectSkin->mSkinInfo->mX;
		mCheckRect.mTop = pRectSkin->mSkinInfo->mY;
		mCheckRect.mRight = mCheckRect.mLeft + pRectSkin->mSkinInfo->mWidth;
		mCheckRect.mBottom = mCheckRect.mTop + pRectSkin->mSkinInfo->mHeight;
	}

	for( int i = 0; i < MAXPAGE_NUM; ++i )
	{
		mpRadioNode[i] = GetChild( eUIID_GAME_FRIEND_PAGERADIO1 + i );
		if( mpRadioNode[i] )
			mpRadioNode[i]->Hide();
	}
	return true;
}


void cFriendWindow::UpdateSkin()
{
	cUIWindow::UpdateSkin();
	UpdateButton();
}

///
void cFriendWindow::OnListBoxChanged( cUINode*, unsigned int )
{
	if( !mpFriendList ) return;

	unsigned int selectIdx = mpFriendList->GetSelectIndex();
	sFriendData* data = (sFriendData*)mpFriendList->GetExtraData( selectIdx );
	if( data == 0 )
	{
		assert(0);
		return;
	}

	bool connect = ( data->mGameIn == 1 ) ? true : false;

	if( mParty )
		mParty->SetEnabled( connect );
	if( mWhisper )
		mWhisper->SetEnabled( connect );
}

///
void cFriendWindow::OnCommand( cUINode*, unsigned int id )
{
	if( !mpFriendList )
		return;

	switch( id )
	{
	case eUIID_GAME_FRIEND_CLOSE:
		Hide();
		break;
	case eUIID_GAME_FRIEND_PARTYBUTTON:
		{
			unsigned int selectIdx = mpFriendList->GetSelectIndex();
			LPCTSTR friendName = mpFriendList->GetText( selectIdx );

			/// 파티 요청 
			PARTYMAN->RequestPartyAdd( friendName );
		}
		break;
	case eUIID_GAME_FRIEND_WHISPERBUTTON:
		{
			/// 귓속말 자동입력
			cChatWindow* pWindow = (cChatWindow*)UIMAN->GetContainer( eUIID_GAME_CHATWINDOW );
			if( pWindow )
			{
				/// 선택된 친구의 아이디를 가져옴
				unsigned int selectIdx = mpFriendList->GetSelectIndex();

				/// "/w %s "
				cStringT str;
				str.Format( UIMAN->GetUIText(10005), mpFriendList->GetText( selectIdx ) );

				/// 채팅윈도우로 포커스 옮기기
				pWindow->SetFocusToEdit();
				pWindow->SetChatText( (LPCTSTR)str.Cstr() );
			}
		}
		break;
	case eUIID_GAME_FRIEND_NOTEBUTTON:
		{
			/// 쪽지쓰기
			cSendNoteWindow* pSend = (cSendNoteWindow*)UIMAN->GetContainer( eUIID_GAME_SENDNOTE_WINDOW );
			if( pSend )
			{
				unsigned int selectIdx = mpFriendList->GetSelectIndex();
				pSend->SetName( mpFriendList->GetText( selectIdx ) );

				if( pSend->IsVisible() == false )
					pSend->ShowTop();
			}
		}
		break;
	case eUIID_GAME_FRIEND_ADDFRIENDBUTTON:
		{
			/// 친구 추가 창 띄우기
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_FRIEND_ADD, 
								GAMERESOURCEMAN->GetGameText( 21 ), // 친구 추가 메시지
								GAMERESOURCEMAN->GetGameText( 18 ), // 친구추가
								eSKIN_EDIT, 0, 0, false, false, MAX_NAME_SIZE );
		}
		break;
	case eUIID_GAME_FRIEND_DELETEFREINDBUTTON:
		if( mpFriendList->GetRowCount() > 0 )
		{
			unsigned int selectIdx = mpFriendList->GetSelectIndex();
			sFriendData* data = (sFriendData*)mpFriendList->GetExtraData( selectIdx );
			if( data == 0 )
				return;

			/// 친구 삭제 창 띄우기
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_FRIEND_DELETE, 
								GAMERESOURCEMAN->GetGameText( 22 ), // 친구 삭제 메시지
								GAMERESOURCEMAN->GetGameText( 19 ), // 친구삭제
								eSKIN_YESNO,
								(void*)data->mIdx
								);
		}
		break;
	default:
		assert(0);
		break;
	}
}

///
void cFriendWindow::OnRadioPressed( cUINode*, unsigned int id )
{
	int row = 0;
	switch( id )
	{
	case eUIID_GAME_FRIEND_PAGERADIO1:	row = 0; break;
	case eUIID_GAME_FRIEND_PAGERADIO2:	row = 10; break;
	case eUIID_GAME_FRIEND_PAGERADIO3:	row = 20; break;
	case eUIID_GAME_FRIEND_PAGERADIO4:	row = 30; break;
	case eUIID_GAME_FRIEND_PAGERADIO5:	row = 40; break;
	default: assert(0); return;
	}	

	if( mpFriendList )
		mpFriendList->ChangeTopIndex( row );
}

/// 접속리스트, 비접속 리스트를 두번 받는다.
void cFriendWindow::AddFriend( MSG_RES_FRIEND_LIST* msgData )
{
	if( mpFriendList ) 
	{
		Clear();

		/// 접속/ 비접속 소팅기능을 위함
		AddConnect( (MSG_RES_FRIEND_LIST*)msgData );
		AddNotConnect( (MSG_RES_FRIEND_LIST*)msgData );
		Update();
	}
}

///
void cFriendWindow::AddConnect( MSG_RES_FRIEND_LIST* msgData )
{
	/// 데이터 삽입 
	for( int i = 0; i < msgData->RowCount; ++i )
	{
		/// 접속상태가 아니면 스킵
		if( msgData->table[i].GameIn != 1 )
			continue;

		/// 제한갯수 이상 입력시 무시
		unsigned long rowCount = mpFriendList->GetRowCount();
		if( rowCount < mpFriendList->GetMaxRowNum() )
		{
			/// 확장데이터 세팅
			sFriendData* exData = new sFriendData;
			exData->mIdx = msgData->table[i].Idx;
			exData->mFriendIdx = msgData->table[i].CharacterIdx;
			exData->mGameIn = msgData->table[i].GameIn;
			exData->mName = msgData->table[i].CharacterName;
			mFriendArr.PushBack( exData );

			/// row 데이터 ( 이미지, 이름, 확장데이터 )
			char imageIdx = GetFriendImage( msgData->table[i].Race, msgData->table[i].Gender );
			cUIImage* pImage = (cUIImage*)mImageArr[ imageIdx ];

			LPCTSTR name = msgData->table[i].CharacterName;
			int row = mpFriendList->AddRow( name, mDefaultColor, exData, pImage );
			if( row > -1 )
			{
				/// 출력 데이터
				cStringT temp, columnStr;
				temp.Format( _T("%s %s"), GAMERESOURCEMAN->GetJobName( msgData->table[i].Job ), 
									      GAMERESOURCEMAN->GetMapName( msgData->table[i].MapNum ) );
				columnStr.Format( GAMERESOURCEMAN->GetGameText( 39 ), msgData->table[i].Level, (LPCSTR)temp.Cstr() );

				/// 삽입
				mpFriendList->AddColume( row, (LPCTSTR)columnStr.Cstr(), mDefaultColor );
			}
		}
		else
		{
			mAddFriend->SetEnabled( false );
			break;
		}
	}
}

void cFriendWindow::AddNotConnect( MSG_RES_FRIEND_LIST* msgData )
{
	/// 데이터 삽입 
	for( int i = 0; i < msgData->RowCount; ++i )
	{
		/// 등록완료 상태면 스킵
		if( msgData->table[i].GameIn == 1 )
			continue;

		/// 제한갯수 이상 입력시 무시
		unsigned long rowCount = mpFriendList->GetRowCount();
		if( rowCount < mpFriendList->GetMaxRowNum() )
		{	
			/// 확장데이터 세팅
			sFriendData* exData = new sFriendData;
			exData->mIdx = msgData->table[i].Idx;
			exData->mFriendIdx = msgData->table[i].CharacterIdx;
			exData->mGameIn = msgData->table[i].GameIn;
			exData->mName = msgData->table[i].CharacterName;
			mFriendArr.PushBack( exData );

			/// row 데이터 ( 이미지, 이름, 확장데이터 )
			char imageIdx = GetFriendImage( msgData->table[i].Race, msgData->table[i].Gender );
			cUIImage* pImage = (cUIImage*)mImageArr[ imageIdx ];

			LPCTSTR name = msgData->table[i].CharacterName;
			int row = mpFriendList->AddRow( name, eCOLOR_DARKGRAY, exData, pImage );
			if( row > -1 )
			{
				cStringT columnStr;
				columnStr.Format( GAMERESOURCEMAN->GetGameText( 38 ) );
		
				mpFriendList->AddColume( row, (LPCTSTR)columnStr.Cstr(), eCOLOR_DARKGRAY );
			}
		}
		else
		{
			mAddFriend->SetEnabled( false );
			break;
		}
	}

	/// 친구 신청이 오면 출력
	for( int i = 0; i < msgData->RowCount; ++i )
	{
		/// 등록신청
		if( msgData->table[i].Status == 1 )
		{
			cStringT Message;
			Message.Format( GAMERESOURCEMAN->GetGameText( 40 ), msgData->table[i].CharacterName );

			/// 친구등록 신청
			UIMAN->CreateModal(	eStage_Game,
								eMBEVENT_FRIEND_ADD_REQ, 
								(LPCTSTR)Message.Cstr(),			// 친구 요청 메시지
								GAMERESOURCEMAN->GetGameText( 20 ), // 친구 요청
								eSKIN_YESNO,
								(void*)msgData->table[i].Idx );
			break;
		}
	}
}

void cFriendWindow::Update()
{
	/// 선택된 리스트에 따른 버튼 업데이트
	if( !mpFriendList || !mDelFriend )
		return;

	bool connect = false;
	if( mpFriendList->GetRowCount() == 0 )
	{
		mDelFriend->SetEnabled( false );
	}
	else
	{
		mDelFriend->SetEnabled( true );

		unsigned int selectIdx = mpFriendList->GetSelectIndex();
		sFriendData* data = (sFriendData*)mpFriendList->GetExtraData( selectIdx );
		if( data && data->mGameIn == 1 )
			connect = true;
	}

	if( mParty )
		mParty->SetEnabled( connect );
	if( mWhisper )
		mWhisper->SetEnabled( connect );

	///
	UpdateButton();
}

void cFriendWindow::UpdateButton()
{
	if( !mpFriendList )
	{
		assert(0);
		return;
	}

	/// 버튼 위치 업데이트
	int total = mpFriendList->GetRowCount() - 1;
	int page = ( total / 10 );

	for( int i = 0; i < MAXPAGE_NUM; ++i )
	{
		if( mpRadioNode[i] )
		{
			if( i <= page )
				mpRadioNode[i]->Show();
			else
				mpRadioNode[i]->Hide();
		}
	}

	/// 위치 조정
	if( mpRadioNode[0] )
	{
		int w = mpRadioNode[0]->GetAbsoluteRect().GetWidth();	
		int x = mCheckRect.mLeft + (int)((mCheckRect.GetWidth() - (w*(page+1))) * 0.5f);
		for( int i = 0; i <= page; ++i )
		{
			cUIPos pos;
			pos.mX = x + (w*i);
			pos.mY = mpRadioNode[i]->GetRelativeRect().mTop;
			mpRadioNode[i]->SetRelativePos( pos );
		}

		mpRadioNode[0]->SetPress( true );
	}
}

char cFriendWindow::GetFriendImage( char race, char gender )
{
	/// 남자면 그대로 리턴, 성별이 여자면 검사
	char result = race;
	if( gender == eGENDER_FEMALE )
	{
		if( race == eRACE_HUMAN ) result = 3;
		if( race == eRACE_BEAST ) result = 4;
		if( race == eRACE_ELF ) result = 5;
	}
	return result;
}

sFriendData* cFriendWindow::GetFriendData( int friendIdx )
{
	for( unsigned int i = 0; i < mFriendArr.GetSize(); ++i )
	{
		sFriendData* data = (sFriendData*)mFriendArr[i];
		if( data && data->mFriendIdx == friendIdx )
			return data;
	}
	return 0;
}

///
void cFriendWindow::CreateImage( const cString& skinname )
{
	cUISkin* pSkin = UIMAN->GetSkin();
	if( !pSkin )
	{
		assert(0);
		return;
	}

	cUINodeSkin* pImgSkin = pSkin->GetNodeSkin( skinname );
	if( pImgSkin == 0 )
	{
		assert( 0 && "failed to find Image skin" );
		return;
	}

	cUIImage* pImage = new cUIImage( pImgSkin->mpTexture );

	unsigned int tx = pImgSkin->mSkinInfo->mTexX;
	unsigned int ty = pImgSkin->mSkinInfo->mTexY;
	unsigned int tw = pImgSkin->mSkinInfo->mTexWidth;
	unsigned int th = pImgSkin->mSkinInfo->mTexHeight;
	pImage->SetTextureRect( tx, ty, tx + tw, ty + th );

	unsigned int x = pImgSkin->mSkinInfo->mX;
	unsigned int y = pImgSkin->mSkinInfo->mY;
	unsigned int w = pImgSkin->mSkinInfo->mWidth;
	unsigned int h = pImgSkin->mSkinInfo->mHeight;

	cUIRect desc;
	desc.Set( x, y, x + w, y + h ); 
	pImage->SetScreenRect( desc );

	mImageArr.PushBack( pImage );
}

void cFriendWindow::OnNetLock( int lockTry )
{
	if( mParty )
		mParty->NetLock( lockTry );
	if( mAddFriend )
		mAddFriend->NetLock( lockTry );
	if( mDelFriend )
		mDelFriend->NetLock( lockTry );
}

void cFriendWindow::OnNetUnLock( int lockTry )
{
	if( mParty )
		mParty->NetUnLock( lockTry );
	if( mAddFriend )
		mAddFriend->NetUnLock( lockTry );
	if( mDelFriend )
		mDelFriend->NetUnLock( lockTry );

	///
	Update();
}

bool cFriendWindow::IsFriend( unsigned long playerIdx )
{
	return (GetFriendData( playerIdx ) != 0);
}
