/* ==========================================================================
* 파    일 : GuildManager.h
* 목    적 : 
* 작 성 자 : 김가람
* 작 성 일 : 2008-10-31
* 주의사항 :
*===========================================================================*/
#pragma once

/// 길드 갱신시간
const unsigned long GUILD_UPDATETIME = 10 * 1000;			// 10초
const unsigned long GUILDDB_UPDATETIME = 60 * 60 * 1000;	// 1시간
const unsigned long	CONNECT_UPDATETIME = 2 * 60 * 60 * 1000;	// 2시간

class cGuild;
class cPlayer;

class cGuildManager
{
	static cGuildManager*	mpSingleton;

public:
	cGuildManager();
	~cGuildManager();

	bool Init();

	/// 해당 유저에게 길드정보 보내기
	void SendGuildInfo( ULONG_PTR socketContext, cPlayer* player, unsigned long idx );
	void SendGuildInfo( cPlayer* player, unsigned long idx );
	
	/// 길드에 추가 유저 정보 보내주기
	void SendGuildUserAdd( cGuild* guild, long characterIdx, char level, long job, short mapnum, wchar_t* name, char position, DWORD channelNum );

	/// 길드에 탈퇴 유저 정보 보내주기
	void SendGuildUserOut( cGuild* guild, unsigned long characterIdx );

	/// 길드에 추방 유저 정보 보내주기
	void SendGuildUserCut( cGuild* guild, unsigned long characterIdx );

	/// 일정시간마다 데이터 갱신후 보내기
	void SendGuildUpdateInfo( cGuild* guild );

	/// 길드유저가 직위가 변경되었음을 알려준다
	void SendGuildChangePosition( cGuild* guild, unsigned long characterIdx, char position );

	/// 길드공지 변경 및 보내기
	bool SendGuildNotice( unsigned long idx, wchar_t* notice );

	/// 마크 인덱스 변경 보내기
	void SendGuildMarkUpdate( cGuild* guild, unsigned long markIdx );

	/// 마크 보내주기
	bool SendGuildMark( unsigned long idx, cPlayer* player );

	/// 길드채팅
	void SendGuildChat( cPlayer* hero, wchar_t* message, unsigned short number );

	/// 전체 길드정보 저장
	bool SaveAllDB();

	/// 플레이어 나감
	void PlayerMapOut( cPlayer* hero );

	/// 플레이어 들어옴 (맵이동)
	void PlayerMapIn( cPlayer* hero );

	/// 채널 정보 갱신
	bool GuildUpdateChannel( unsigned long idx, unsigned long characterIdx, DWORD channelNum );

	/// 내 길드원인지 검사
	TB_GUILD_USER* IsMyGuildUser( unsigned long idx, unsigned long characterIdx );

	/// 직위변경 검사
	bool CheckChangePosition( cPlayer* hero, unsigned long characterIdx, char newposition );

	/// 길드마크 인덱스 생성
	unsigned long CreateMarkIndex();

	/// 길드 정보 갱신 및 전송 플래그
	bool RequestUpdateUser( unsigned long idx, unsigned long characterIdx, char level, long job );

public:
	void Release();
	void Process( unsigned long elasedTime, unsigned long accumTime );

	/// 길드 생성
	bool AddGuild( GUILD_CREATE* data, cPlayer* master );
	bool DeleteGuild( unsigned long idx );

	/// 신청 정보 저장
	bool AddRequest( unsigned long recvIdx, unsigned long reqIdx );
	void DelRequest( unsigned long recvIdx );
	unsigned long GetRequest( unsigned long recvIdx );

	/// 서버, 채널 SYN 메세지
	bool SynAddGuild( void* msg, DWORD channelNum );
	bool SynAddGuildUser( void* msg, DWORD channelNum );
	bool SynCutGuilduser( void* msg );
	bool SynOutGuilduser( void* msg );
	bool SynUpdateMark( void* msg );
	bool SynUpdateGuildUserInfo( void* msg );
	bool SynGuildChat( void* msg );
	bool SynGuildNote( void* msg );
	bool SynGuildConnect( void* msg, DWORD channelNum );

	/// 길드원 접속정보 보내기
	bool SendGuildConnect( DWORD reqChannelNum );
	void ClearGuildConnect();

	/// 초기 길드 정보 생성
	void SetGuildTotalLength( DWORD length );
	void SetGuildLength( DWORD length );

	bool VerifyGuildSelect( TB_GUILD* guild );
	bool VerifyGuildUser( unsigned long idx, TB_GUILD_USER* user );

	///
	cGuild* GetGuild( unsigned long idx );
	wchar_t* GetGuildName( unsigned long idx );
	unsigned long GetGuildMarkIndex( unsigned long idx );
	bool FindGuildName( wchar_t* name );

	/// 데이터 정확성 검사
	bool CheckGuildLength();
	bool CheckGuildTotal();
	bool CheckGuildSaveTotal();

protected:
	/// 길드정보 DB 업데이트
	void SaveDBGuild( cGuild* guild );

public:
	static cGuildManager* Get();

private:
	/// 길드 맵
	typedef tPointerHashMap<unsigned long, void*> cGuildMap;
	cGuildMap	mGuildMap;

	/// 신청 정보	
	typedef tHashMap<unsigned long, unsigned long> cJoinMap;	
	cJoinMap	mJoinMap;

	/// 데이터 확인용
	DWORD mGuildTotalLength; /// 총 select 해야할 길드 갯수 ( DB 레코드 수 )
	DWORD mGuildTotalOffset; /// 총 select 해야할 길드 갯수 ( DB 레코드 수 )
	DWORD mGuildSaveOffset;	/// 총 저장 해야할 길드 갯수

	DWORD mGuildSelectLength; /// 실제 존재하는 길드 갯수 ( DB 레코드 수 )

	/// 길드 마크 생성
	unsigned long mMarkIndexGen;

	/// 정보갱신 시작시간
	long	mAccumTime;
};

inline unsigned long cGuildManager::CreateMarkIndex()
{
	if( mMarkIndexGen >= ULONG_MAX )
	{
		assert(0);
		return 0;
	}
	return ++mMarkIndexGen;
}

inline void cGuildManager::SetGuildTotalLength( DWORD length )
{
	mGuildTotalLength = length;
}

inline void cGuildManager::SetGuildLength( DWORD length )
{
	mGuildSelectLength = length;
}

inline cGuildManager* cGuildManager::Get()
{
	return mpSingleton;
}

#define GUILDMAN cGuildManager::Get()
