/* ====================================================================
 * 파    일 :	gameProcess.h
 * 목    적 :	
 * 작 성 자 :	곽철중
 * 작 성 일 :	06/12/22
 * 주의사항 :	
 * =================================================================== */
#ifndef __GAME_PROCESS_H__
#define __GAME_PROCESS_H__

//#ifndef WINVER
//#define WINVER          0x0500
//#endif
//
//#ifndef _WIN32_WINNT
//#define _WIN32_WINNT    0x0500
//#endif

#pragma once

#include "iocpserver.h"

#include "stdafx.h"

#include "packet.h"
#include "protocol.h"
#include "commonnetworkmsgstruct.h"

#include "memorypool.h"

#include "RandomTable.h"
#include "Player_Common.h"
#include "GridManager.h"
#include "ObjectManager.h"
#include "AIManager.h"
#include "SkillScript.h"
#include "SkillManager.h"
#include "AppTimer.h"
#include "Status_Common.h"
#include "DamageCalc.h"
#include "StageScript.h"
#include "ItemManager.h"
#include "CooltimePool.h"
#include "TakeDamagePool.h"
#include "ItemCountPool.h"
#include "PartyManager.h"
#include "TriggerManager.h"
#include "QuestManager.h"
#include "FileSystem.h"
#include "DuelManager.h"
#include "PVPManager.h"
#include "TitleManager.h"
#include "GuildManager.h"
#include "NoteManager.h"
#include "GatheringScript.h"

#include "gamesrvdefines.h"
#include "logprotocol.h"
#include "serverprotocol.h"

// Common Database Flag
#define COMMON_DB_CHECK						0x00000001	// COMMON DB 01 bit
#define COMMON_DB_CHARACTER_LIST			0x00000002	// COMMON DB 02 bit
#define COMMON_DB_CHARACTER_NAME			0x00000004	// COMMON DB 03 bit
#define COMMON_DB_CHARACTER_INSERT			0x00000008	// COMMON DB 04 bit
#define COMMON_DB_CHARACTER_DELETE			0x00000010	// COMMON DB 05 bit
#define COMMON_DB_CHARACTER_SELECT			0x00000020	// COMMON DB 06 bit
#define COMMON_DB_CHARACTER_UPDATE			0x00000040	// COMMON DB 07 bit
#define COMMON_DB_CHARACTER_EQUIP			0x00000080	// COMMON DB 08 bit
#define COMMON_DB_CHARACTER_MONEY			0x00000100	// COMMON DB 09 bit
#define COMMON_DB_CHARACTER_ACTIVE_WEAPON   0x00000200	// COMMON DB 10 bit
#define COMMON_DB_NOTE_SELECT				0x00000400	// COMMON DB 11 bit
#define COMMON_DB_NOTE_INSERT				0x00000800	// COMMON DB 12 bit
#define COMMON_DB_NOTE_DELETE				0x00001000	// COMMON DB 13 bit
#define COMMON_DB_FRIEND_SELECT				0x00002000	// COMMON DB 14 bit
#define COMMON_DB_FRIEND_INSERT				0x00004000	// COMMON DB 15 bit
#define COMMON_DB_FRIEND_UPDATE				0x00008000	// COMMON DB 16 bit
#define COMMON_DB_FRIEND_DELETE				0x00010000	// COMMON DB 17 bit
#define COMMON_DB_SPREAD_VALUE				0x00020000	// COMMON DB 18 bit
#define COMMON_DB_TAROT_RESULT				0x00040000	// COMMON DB 19 bit
#define COMMON_DB_COMEINGAME				0x00080000	// COMMON DB 20 bit
#define COMMON_DB_STALL_SELL_SEARCH			0x00100000	// COMMON DB 21 bit
#define COMMON_DB_STALL_SELL_CLEAR			0x00200000	// COMMON DB 22 bit
#define COMMON_DB_SHORTCUT_UPDATE			0x00400000	// COMMON DB 23 bit
#define COMMON_DB_GAME_IN_OUT_COMPLETE		0x00800000	// COMMON DB 24 bit
#define COMMON_DB_LOGOUT					0x01000000	// COMMON DB 25 bit
#define COMMON_DB_SKILL_INFLUENCE_DELETE	0x02000000	// COMMON DB 26 bit
#define COMMON_DB_GOTO_INSTANT_DUNGEON		0x04000000	// COMMON DB 27 bit
#define COMMON_DB_RETURN_MAP				0x08000000	// COMMON DB 28 bit
#define COMMON_DB_MEMBER_SELECT				0x10000000	// COMMON DB 29 bit


enum SERVER_TYPE
{
	_E_ST_NORMAL_MAP_ = 0,				// 일반 맵 서버
	_E_ST_ID_PVP_,						// 인스턴트 던전 서버 - PVP
};


enum GAME_PROCESS_REQUEST_TYPE
{
	// DEFAULT_GAME_PROCESS
	GAME_PROCESS_REQUEST = 0x4000,		// DEFAULT_GAME_PROCESS(0x4000) - defined gamesrv.h file
	// MAX
	MAX_GAME_PROCESS
};

struct ChannelList
{
	bool used;
	BYTE status;
};

class cGameProcess :
	public cIocpServer
{
private:
	double           mDuringSkill;
	double           mDuringObject;
	double           mDuringAI;
	double           mDuringDuel;
	double           mDuringPVP;
	double           mDuringGrid;

	char             mLastCategory;
	char             mLastProtocol;
	u_short          mLastPacketSize;

	cFileSystem*     mpFileSystem;

	// 070110 PKH 타이머
	cAppTimer*       mpAppTimer;
	unsigned long	 mElapsedTime;	// 061127 PKH 프로세스간 경과 시간
	unsigned long	 mAccumTime;	// 061201 PKH 처음부터 진행된 시간

	cMemoryPool*     mpMemoryPool;

	cRandomTable*    mpRandomTable;
	cPackedData*     mpPackedData;
	cGridManager*    mpGridManager;
	cGatheringScript* mpGatheringScript;
	cObjectManager*  mpObjectManager;
	cAIManager*      mpAIManager;
	cSkillManager*   mpSkillManager;
	cStageScript*	 mpStageScript;
	cItemManager*    mpItemManager;
	cCooltimePool*   mpCooltimePool;
	cTakeDamagePool* mpTakeDamagePool;
	cItemCountPool*  mpItemCountPool;
	cPartyManager*	 mpPartyManager;
	cTriggerManager* mpTriggerManager;
	cQuestManager*	 mpQuestManager;
	cDuelManager*    mpDuelManager;
	cPVPManager*     mpPVPManager;
	cTitleManager*	 mpTitleManager;
	cGuildManager*	 mpGuildManager;
	cNoteManager*	 mpNoteManager;

private:
// 환경변수.
	union
	{
		struct
		{
			bool itemDefine       : 1;
			bool itemAbility      : 1;
			bool itemCoolitme2    : 1;
			bool itemLimit        : 1;
			bool itemCard         : 1;
			bool itemCardSlot     : 1;
			bool itemTarot        : 1;
			bool itemEnhanced     : 1;
			bool itemEnhancedRate : 1;
			bool itemDisjoint     : 1;
			bool itemChange       : 1;
			bool guild			  : 1;
		} mRequestImport;
		long mRequestImportData;
	};
	union
	{
		struct
		{
			bool itemDefine       : 1;
			bool itemAbility      : 1;
			bool itemCooltime2    : 1;
			bool itemLimit        : 1;
			bool itemCard         : 1;
			bool itemCardSlot     : 1;
			bool itemTarot        : 1;
			bool itemEnhanced     : 1;
			bool itemEnhancedRate : 1;
			bool itemDisjoint     : 1;
			bool itemChange       : 1;
			bool guild			  : 1;
		} mCompleteImport;
		long mCompleteImportData;
	};
	union
	{
		struct
		{
			bool importItemTables       : 1;
			bool verifyDefaultItems     : 1;

			bool channelCheck           : 1;
			bool initGameDB             : 1;

			bool channelSyn             : 1;

			bool shutdownGameDB         : 1;
			bool shutdownAccountDB      : 1;

			bool guildDB				: 1;
		} mRequest;
		long mRequestData;
	};
	union
	{
		struct
		{
			bool startLog               : 1;
			bool socketContext          : 1;
			bool ioContext              : 1;

			bool importItemTables       : 1;
			bool verifyDefaultItems     : 1;

			bool channelCheck           : 1;
			bool initGameDB             : 1;

			bool channelSyn             : 1;

			bool shutdownGameDB         : 1;
			bool shutdownAccountDB      : 1;
			bool endLog                 : 1;

			bool guildDB				: 1;
			bool guildConnectSyn		: 1;
		} mComplete;
		long mCompleteData;
	};
	struct
	{
		long       cid;
		PVP_STATUS status;
		long       timer;
	} mPVPData;

	DWORD            mFrame;
	DWORD            mFpsTick;
	bool             mThreadPriority;
	DWORD            mThreadPriorityTick;

	DWORD            mElapsedTick;
	DWORD            mMinElapsedTick;
	DWORD            mMaxElapsedTick;

	TCHAR*           mServerInetnum;
	wchar_t          mServerName[51];
	DWORD            mServerNum;
	DWORD            mChannelNum;
	SERVER_TYPE      mType;
	SERVER_STATUS    mStatus;

	ChannelList      mChannelList[MAX_CHANNEL];

	DWORD            mTTLTick;
	DWORD            mStatusSyncTick;

public:
	unsigned long    GetAccumTime            ( ) { return mAccumTime; }

public:
// LOG 관련 메소드.
	bool             PostServerEvent         ( LPCTSTR format, ... );
	bool             PostMemberEvent         ( char type, char category, long memberIdx, char* message );
	bool             PostCharacterEvent      ( char category, long memberIdx, long serverIdx, long characterIdx, char* message );
	bool             PostMoneyEvent          ( long characterIdx, long before, long after, LPCTSTR format, ... );
	bool             PostDepositEvent        ( long characterIdx, long before, long after, char* message );
	bool             PostInventoryEvent      ( char category, long characterIdx, TB_INVENTORY* inventory, char* message );
	bool			 PostQuestEvent		     ( char category, long characterIdx, long questIdx, char* message );
	bool			 PostGuildEvent			 ( long characterIdx, long guildIdx, char guildPosition, char* message );

public:
// GAME SYNC 관련 메소드.
	bool             PostPVPStatus           ( BYTE status );
	bool             PostPvPNotice           ( unsigned char leftMinute );
	bool			 PostGuildCreate		 ( GUILD_CREATE* guildCreate, cPlayer* player );
	bool			 PostGuildDelete		 ( long idx );
	bool			 PostGuildUserAdd		 ( long idx, cPlayer* player );
	bool			 PostGuildUserCut		 ( long idx, long characterIdx );
	bool			 PostGuildUserOut		 ( long idx, long characterIdx );
	bool			 PostGuildGivePosition   ( long idx, long characterIdx, char position );
	bool			 PostGuildUpdateMark     ( long idx, long markIdx, BYTE* mark, int size );
	bool			 PostGuildNotice		 ( long idx, wchar_t* notice );
	bool		     PostGuildChat			 ( long idx, wchar_t* name, wchar_t* message, sInventory* inventory );
	bool			 PostGuildUpdateChannel  ( long idx, long characterIdx, bool connect );
	bool			 PostGuildUpdateInfo	 ( long idx, long characterIdx, char level, long job );
	bool			 PostGuildNote			 ( GUILDNOTE_INSERT* guildNoteInsert );
		
	/// 길드 접속 관련 동기화요청
	bool			 PostGuildRequestConnect ( );

	///
	bool             PostMonRegenStart       ( unsigned long switchGroup );
	bool             PostMonRegenStop        ( unsigned long switchGroup );

	/// 귓속말 
	bool			 PostChatWhisper		 ( DWORD recvChannel, unsigned long senderIdx, wchar_t* senderName, wchar_t* recvName, wchar_t* message, sInventory* inven );
	bool			 PostChatWhisperResult	 ( DWORD sendChannel, int errorCode, unsigned long senderIdx, wchar_t* recvName, wchar_t* message, sInventory* inven );

	/// 쪽지
	bool			 PostChatNote			 ( DWORD recvChannel, wchar_t* recvName, tbNOTE* note );

private:
// SQL 관련 메소드 System.
	bool             VerifyItemDefine        ( void );
	bool             VerifyItemAbility       ( void );
	bool             VerifyItemCooltime2     ( void );
	bool             VerifyItemLimit         ( void );
	bool             VerifyItemCard          ( void );
	bool             VerifyItemCardSlot      ( void );
	bool             VerifyItemTarot         ( void );
	bool             VerifyItemEnhanced      ( void );
	bool             VerifyItemEnhancedRate  ( void );
	bool             VerifyItemDisjoint      ( void );
	bool             VerifyItemChange        ( void );

	bool             ItemDefine              ( long idx );
	bool             ItemAbility             ( long idx );
	bool             ItemCooltime2           ( long idx );
	bool             ItemLimit               ( long idx );
	bool             ItemCard                ( long idx );
	bool             ItemCardSlot            ( long idx );
	bool             ItemTarot               ( long idx );
	bool             ItemEnhanced            ( long idx );
	bool             ItemEnhancedRate        ( long idx );
	bool             ItemDisjoint            ( long idx );
	bool             ItemChange              ( long idx );

	bool             VerifyDefaultItems      ( void );

	bool             ChannelCheck            ( short serverNum, short channelNum, char* inetnum, unsigned long ipv4, unsigned short port );
	bool             InitGameDB              ( );
	bool             ShutdownGameDB          ( );
	bool             ShutdownAccountDB       ( );

public:
// SQL 관련 메소드 Game.
	bool             CharacterList           ( PerSocketContext* perSocketContext, long memberIdx );

	// 인벤토리
	bool             InventorySelect         ( PerSocketContext* perSocketContext, long characterIdx );
	bool             InventoryDelete         ( PerSocketContext* perSocketContext, INVENTORY_WARNING warning, long characterIdx, long inventoryIdx );
	bool             InventoryCooltimeSelect ( PerSocketContext* perSocketContext, long characterIdx );
	bool             InventorySwap           ( PerSocketContext* perSocketContext, long idx1, short number1, long idx2, short number2 );
	bool             InventoryMove           ( PerSocketContext* perSocketContext, long characterIdx, long idx, short number );
	bool             InventoryExcept         ( PerSocketContext* perSocketContext, long characterIdx, long idx, short number );
	bool             InventoryMerge          ( PerSocketContext* perSocketContext, long idx1, long idx2 );

	// 쪽지
	bool             NoteSelect              ( PerSocketContext* perSocketContext, long characterIdx );
	bool             NoteInsert              ( PerSocketContext* perSocketContext, long characterIdx1, wchar_t* characterName2, wchar_t* message );
	bool             NoteDelete              ( PerSocketContext* perSocketContext, long characterIdx, long rowCount, long idx[1] );

	bool             GuildNoteInsert         ( PerSocketContext* perSocketContext, long characterIdx1, wchar_t* message, long rowCount, long* characterIdx2 );

	// 친구
	bool             FriendSelect            ( PerSocketContext* perSocketContext, long characterIdx );
	// 스프레드(타로카드)
	bool             ItemSpreadValue         ( PerSocketContext* perSocketContext, long index, long value[10] );
	// 타로카드(스킬효과)
	bool             ItemTarotResult         ( PerSocketContext* perSocketContext, long itemDefineIndex, long value );

	// 스킬
	bool             SkillSelect		     ( PerSocketContext* perSocketContext, unsigned long characterIdx );
	bool             SkillInsert		     ( PerSocketContext* perSocketContext, unsigned long characterIdx, unsigned long skillClassIdx, unsigned long money, unsigned short sp, unsigned char skillLevel, unsigned long skillPoint );
	bool             SkillUpdate		     ( PerSocketContext* perSocketContext, unsigned long characterIdx, unsigned long skillClassIdx, unsigned char skillStep, unsigned long money, unsigned short sp, unsigned char skillLevel, unsigned long skillPoint );
	bool             SkillCoolTime		     ( PerSocketContext* perSocketContext, unsigned long characterIdx );

	// 효과
	bool             SkillInfluenceSelect    ( PerSocketContext* perSocketContext, unsigned long characterIdx );
	bool             SkillInfluenceDelete    ( PerSocketContext* perSocketContext, unsigned long characterIdx );
	bool             SkillInfluenceInsert    ( PerSocketContext* perSocketContext, unsigned long characterIdx );

	// 큇슬롯(Shortcut)
	bool             ShortcutSelect          ( PerSocketContext* perSocketContext, unsigned long characterIdx );

	// 퀘스트
	bool			 QuestSelect		     ( PerSocketContext* perSocketContext, long characterIdx );
	bool			 QuestCompleteSelect     ( PerSocketContext* perSocketContext, long characterIdx );
	bool			 QuestRemove		     ( PerSocketContext* perSocketContext, long dbIdx );

	// 호칭
	bool			 TitleSelect			 ( PerSocketContext* perSocketContext, long characterIdx );

	// 길드
	bool			 VerifyGuild			 ( void );
	bool			 GuildSelect			 ( long idx );	/// DB 고유번호
	bool			 GuildUserSelect		 ( long idx );	/// 길드 인덱스

	bool			 GuildCreate			 ( PerSocketContext* perSocketContext, long characterIdx, wchar_t* guildName, wchar_t* masterName );
	bool			 GuildDelete			 ( PerSocketContext* perSocketContext, long idx, long characterIdx );
	bool			 GuildUserAdd			 ( PerSocketContext* perSocketContext, long idx, long characterIdx );
	bool			 GuildUserOut			 ( PerSocketContext* perSocketContext, long idx, long characterIdx );
	bool			 GuildUserCut			 ( PerSocketContext* perSocketContext, long idx, long characterIdx );
	bool			 GuildUserGivePosition   ( PerSocketContext* perSocketContext, long idx, long characterIdx, char position );
	bool			 GuildMarkUpdate		 ( PerSocketContext* perSocketContext, long idx, long markIdx, BYTE* mark );

	/// 제조 스킬
	bool             MakeSkillSelect         ( PerSocketContext* perSocketContext, unsigned long characterIdx );
	bool             RecipeCoolTime		     ( PerSocketContext* perSocketContext, cPlayer* hero );

	/// 운세 저장 정보
	bool			 FortuneSelect			 ( PerSocketContext* perSocketContext, unsigned long characterIdx );

	/// 귓말 - 유저 접속 정보
	bool			 WhisperMemberSelect	 ( PerSocketContext* perSocketContext, wchar_t* recvName, wchar_t* message, short slotIndex );

	/// 쪽지 - 유저 접속 정보
	bool			 NoteMemberSelect		 ( PerSocketContext* perSocketContext, wchar_t* recvName, TB_NOTE* note );

private:
// 서버 관련 메소드 - 보조.
	bool             IsCharacterName         ( wchar_t* name, int len );

	bool             ResMsgRoot              ( PerSocketContext* perSocketContext, char category, char protocol );
	bool             ResMsgError             ( PerSocketContext* perSocketContext, char category, char protocol, long error );
	bool             ResMsgError             ( unsigned long connectionIdx, char category, char protocol, long error );
	bool             ResCharacterList        ( PerSocketContext* perSocketContext, long rowCount, TB_CHARACTER* tbCharacter );
	bool             ResChannelList          ( PerSocketContext* perSocketContext );

private:
// 서버 관련 메소드 - 보조.
	bool             BatchComplete           ( DWORD currentTick, PerSocketContext* perSocketContext, void* ptr );
	bool             UpdateComplete          ( PerSocketContext* perSocketContext, bool logout=false, bool shutdown=false );

	void             GameManager             ( DWORD currentTick );
	void             SocketManager           ( DWORD currentTick );
	void             ChannelManager          ( DWORD currentTick );

	void             BackendThreadBegin      ( void );
	void             BackendThreadProc       ( void );
	void             BackendThreadEnd        ( void );
	void             BackendThreadFps        ( DWORD currentTick );

private:
// 서버 관련 메소드 - 보조.
	void             Decrypt                 ( BYTE key, long len, char* ptr );
	void             Encrypt                 ( BYTE key, long len, char* ptr );

private:
// 서버 관련 메소드 - 주.
	bool             SendExec                ( PerIoContext* perIoContext );

	bool             AcceptComplete          ( PerSocketContext* perSocketContext );
	bool             SendComplete            ( PerSocketContext* perSocketContext, PerIoContext* perIoContext, DWORD bytesTransferred );
	bool             RecvComplete            ( PerSocketContext* perSocketContext, PerIoContext* perIoContext, DWORD bytesTransferred );
	bool             CallbackComplete        ( PerSocketContext* perSocketContext, PerIoContext* perIoContext, DWORD bytesTransferred );

public:
// 클래스 생성 및 공용 메소드.
	cGameProcess(DWORD serverNum, DWORD channelNum, TCHAR* inetnum=NULL);

	bool             Initialize              ( char* ipAddr="", unsigned short port=10000, unsigned short numWorkerThreads=2, unsigned short bufferLength=HAL_TCP_PACKET_SIZE );
	void             Shutdown                ( DWORD maxWait=INFINITE );
	bool             CloseCID                ( DWORD cid, bool how=false );

	long             GetCID                  ( ) { return MAKECID( (WORD)mServerNum, (WORD)mChannelNum); }
	DWORD            GetChannelNum           ( ) { return mChannelNum; }
	SERVER_TYPE      GetServerType           ( ) { return mType; }

	char*            GetSQL                  ( void** handle, UINT_PTR iParam );

	bool             SendSQL                 ( void* handle, unsigned long length );
	bool             SendSQL                 ( PerSocketContext* perSocketContext, void* handle, unsigned long length, long commonDatabase=0 );
	bool             SendSQL                 ( unsigned long connectionIdx, void* handle, unsigned long length, long commonDatabase=0 );

	void             ReleaseSQL              ( void* handle, unsigned long length );

	PerIoContext*    GetIoContext            ( u_long request );
	void             ReleaseIoContext        ( PerIoContext* perIoContext, char* callStack=NULL );

	bool             SendToUser              ( unsigned long connectionIdx, char* msg, unsigned long length );

	MSGROOT*         GetMsgRoot              ( void** handle, PerSocketContext* perSocketContext, char category=0, char protocol=0 );
	MSGROOT*         GetMsgRoot              ( void** handle, unsigned long connectionIdx, char category=0, char protocol=0 );
	bool             SendMsgRoot             ( void* handle, unsigned long length );
	void             SendMsgRoot             ( char* buffer, unsigned long& internal, unsigned long& internalHigh, char* msg, int msgLen );
	void             ReleaseMsgRoot          ( void* handle, unsigned long length );

	bool             QuickSend               ( cBaseObject* object, char* msg, int length );
	bool             QuickSendExcept         ( cBaseObject* object, char* msg, int length );
	bool             QuickSendMap            ( cBaseObject* object, char* msg, int length );
	bool             QuickSendMap            ( unsigned short mapNumber, char* msg, int length );
	bool			 QuickSendExceptMap	     ( cPlayer* object1, cPlayer* object2, char* msg, int length );

// 채널 동기 메소드.
	bool             IsChannelCheck          ( ) { return mComplete.channelCheck; }

	void             ChannelSync             ( );
	void             ChannelStatus           ( long cid, BYTE status );
	void             ServerNotice            ( long cid, wchar_t* message );
	void             ChatShout               ( long cid, unsigned short numfOfMap, long characterIdx, wchar_t* name, wchar_t* message );
	void             PVPStatus               ( long cid, BYTE status );
	void             PVPNotice               ( long cid, unsigned char leftMinute );
	void             GuildSync               ( long cid, char* msg, int len );
	void             GuildConnectSync        ( long cid );
	void             MonsterSync             ( long cid, char* msg, int len );
	void			 ChatSync				 ( long cid, char* msg, int len );

// Backend Thread.
	DWORD            BackendThread           ( void );

public:
// 클래스 파괴 메소드.
	virtual ~cGameProcess(void);

public:
	static cGameProcess* mGameProcess;
};

#define NETWORK2     cGameProcess::mGameProcess

#endif // __GAME_PROCESS_H__
