/* ==========================================================================
* 파    일 : QuestManager.h
* 목    적 : 
* 작 성 자 : 김가람
* 작 성 일 : 2008-01-18
* 주의사항 :
*===========================================================================*/
#pragma once
#include "Lexer.h"
#include "BaseStage.h"
#include "QuestDefine.h"

/// 퀘스트 매니저
class cParser;
class cQuestDefine;
class cUIFuncText;
class cUIFuncTextNode;
class cTrigger;

/// 네트워크 락
enum
{
	eLOCK_QUESTNONE,
	eLOCK_QUESTADD,
	eLOCK_QUESTADDBYITEM,
	eLOCK_QUESTCOMPLETE,
	eLOCK_QUESTREWARD,
	eLOCK_QUESTDELETE,
};

/// 퀘스트 남은시간
struct sQuestTime
{
	long restTime;
	long startTime;
	
	sQuestTime()
	{
		restTime = 0;
		startTime = 0;
	}
};

struct MSG_RES_NPC_QUEST_REWARD;
struct MSG_RES_NPC_QUEST_COMPLETE;
struct MSG_RES_NPC_QUEST_FAIL;

class cQuestManager
{
public:
	static cQuestManager* mpSingleton;

public:
	cQuestManager();
	~cQuestManager();

	bool Init();
	void Close();		/// 맵체인지
	void OpenLoad();	/// 각 스테이지에서의 오픈
	void OpenMapChange();
	void Process( unsigned long accumTime );

	void UpdateNpcQuest( unsigned long npcId, unsigned int status );		/// NPC에 퀘스트 리스트 세팅

	void AddQuestSelect( unsigned long questIndex, bool setQuestWindow = false );
	void DeleteQuestSelect( unsigned long questIndex, bool setQuestWindow = false );
	bool IsSelectQuest( unsigned long questIdx );

	/// 해당 채집아이템 관련 퀘스트가 완료되었는지 검사
	bool IsCompleteGathering( unsigned long questIndex );

	__int64& GetProgress( unsigned int arrIdx );		/// 퀘스트 진행정보
	unsigned long GetQuestIndex( unsigned int arrIdx );
	unsigned char GetQuestStatus( unsigned int arrIdx );
	int GetQuestArrIdx( unsigned long questIdx );
	cQuestDefine* GetQuestDefine( unsigned long questIdx );
	long GetQuestRestTime( unsigned long questIdx );
	unsigned int GetCount( unsigned int mapIdx );		/// 맵에 소유한 퀘스트 총 갯수 리턴
	
	/// 퀘스트 설명용 텍스트 획득
	const cUIFuncTextNode* GetNpcTextNode( unsigned int textid );

	/// 네트워크 메시지
	void NetworkMsgParserLoad( char* msg );			/// Load, MapChange 시 오는 패킷
	void NetworkMsgParser( char* msg );
	void ResQuestAdd( MSG_RES_QUEST_ADD* pmsg );
	void ResQuestComplete( MSG_RES_NPC_QUEST_COMPLETE* pmsg );
	void ResQuestReward( MSG_RES_NPC_QUEST_REWARD* pmsg );

	/// 패킷 쏘기
	bool QuestAddByNpc( unsigned long questIdx, unsigned long npcIndex );	/// 퀘스트 추가 (NPC에 의함)
	bool QuestAdd( unsigned long questIdx );								/// 퀘스트 추가 (NPC에 의함)
	bool QuestAddByItem( unsigned int number );								/// 퀘스트 추가 (아이템에 의함)
	bool QuestComplete( unsigned long questIdx, unsigned long npcIndex );	/// 퀘스트 진행 완료
	bool QuestComplete();
	bool QuestReward( unsigned long questIdx, unsigned long npcIndex );		/// 퀘스트 보상
	void QuestDelete( unsigned int arrIdx );		/// 퀘스트 포기
	void QuestDeleteAuto( unsigned int arrIdx );	/// 퀘스트 자동 포기
	void QuestNewListReSend( unsigned long npcIndex );

	tHashSet<unsigned long>& GetSelectedSet() { return mSelectSet; }

protected:
	void UpdateUIAll();						/// 전체 퀘스트 리스트 갱신
	void UpdateUI();						/// 퀘스트 윈도우만 갱신

	/// 보유, 완료가능 개수 갱신
	void CheckQuestCount();

	///
	void ActiveQuestText( sQuestList* oldQuest, sQuestList* newQuest );

	///
	void AddQuestTime( unsigned long questIdx, unsigned long restTime );
	void DeleteQuestTime( unsigned long questIdx );
	void ClearQuestTime();

	/// 각 맵별로 소유한 퀘스트 갯수 저장
	void CheckCountMap();
	
	/// 락걸기
	void NetLock( int lockTry, unsigned long slotIndex0 = 0 );
	void NetUnLock( int lockTry );
	bool IsNetLock();

public:
	static cQuestManager* GetSingleton();

protected:
	bool Load( const cString& pathname );
	bool LoadQuests( const cString& pathname );
	bool LoadQuestData( cParser& parser, cQuestDefine* p, cTrigger* trigger );

	/// 
	bool LoadTrigger( cParser& parser, cTrigger* trigger );
	bool LoadDuty( cParser& parser, cQuestDuty* duty, __int64& complete );
	bool LoadLimit( cParser& parser, cQuestLimit* limit );
	bool LoadEnd( cParser& parser, cQuestEnd* end );
	bool LoadDefault( cParser& parser, cQuestReward* reward );
	bool LoadSelect( cParser& parser, cQuestReward* select );
	bool LoadFail( cParser& parser, cQuestFail* fail );

	/// 유효성 검사
	bool IsValid( cQuestDefine* define );

private:
	/// 퀘스트 스크립트 정보 맵
	typedef tPointerHashMap<unsigned long, void*> cQuestDefineMap;
	cQuestDefineMap mQuestDefine;

	/// 퀘스트 남은 시간 저장 (전부저장)
	typedef tPointerHashMap<unsigned long, void*> cTimeMap;
	cTimeMap	mTimeMap;

	/// 퀘스트 정보 문자열
	cUIFuncText* mpQuestText;

	/// 퀘스트 정보 저장
	sQuestList mQuest[MAX_KEEPQUEST];
	unsigned int mTotalKeepCount;

	/// 완료가능목록 갯수
	unsigned int mCompleteCount;

	/// 진행중 목록 갯수
	unsigned int mProgressCount;

	/// 삭제나 완료로 인해, check 상태 풀어야하는 퀘스트
	long mCheckQuestIndex;

	/// 임시저장소
	long mTempQuestIndex;
	long mTempNpcIndex;
	unsigned int mTempArrIndex;

	/// 네트워크 관련 락
	bool	mNetLock;
	int		mLockTry;

	/// 선택된 퀘스트 정보 저장
	typedef tHashSet<unsigned long> cSelectSet;
	cSelectSet mSelectSet;

	/// 맵단위 퀘스트 갯수 저장 ( 맵인덱스, 갯수 )
	typedef tHashMap<unsigned int, unsigned int> cCountMap;
	cCountMap mCountMap;
};

inline bool cQuestManager::IsNetLock()
{
	return mNetLock;
}

inline __int64& cQuestManager::GetProgress( unsigned int arrIdx )
{
	return mQuest[arrIdx].check;
}

inline int cQuestManager::GetQuestArrIdx( unsigned long questIdx )
{
	for( unsigned int i = 0; i < mTotalKeepCount; ++i )
	{
		if( mQuest[i].questIdx == questIdx )
			return i;
	}
	return -1;
}

inline unsigned long cQuestManager::GetQuestIndex( unsigned int arrIdx )
{
	return mQuest[arrIdx].questIdx;
}

inline unsigned char cQuestManager::GetQuestStatus( unsigned int arrIdx )
{
	return mQuest[arrIdx].status;
}

inline cQuestManager* cQuestManager::GetSingleton()
{
	return mpSingleton;
}

#define QUESTMAN cQuestManager::GetSingleton()


//////////////////////////////////////////////////////////////////
// 퀘스트 스크립트 토큰
enum
{
	/// 퀘스트 선언
	eTOKEN_QUESTDATA = 100,
	eTOKEN_TITLE,
	eTOKEN_TYPE,
	eTOKEN_DESC,
	eTOKEN_REPEAT,
	eTOKEN_GROUP,
	eTOKEN_SHARETYPE,
	
	eTOKEN_GIVENPC,
	eTOKEN_TAKENPC,
	eTOKEN_TAKEMAP,
	eTOKEN_GIVEITEM,
	eTOKEN_TAKEITEM,
	eTOKEN_SELECTCOUNT,
	eTOKEN_LEVEL,
	
	eTOKEN_NORMALTYPE,
	eTOKEN_SCENARIOTYPE,
	eTOKEN_RACETYPE,
	eTOKEN_CHANGEJOBTYPE,
	
	eTOKEN_CHALLEANGE,
	eTOKEN_REPETITION,

	eTOKEN_ALL,
	eTOKEN_ORDER,

	eTOKEN_DUTY,
	eTOKEN_LIMIT,
	eTOKEN_END,
	eTOKEN_DEFAULTREWARD,
	eTOKEN_SELECTREWARD,
	eTOKEN_FAIL,

	eTOKEN_TALKNPC,
	eTOKEN_HUNT,
	eTOKEN_COLLECT,
	
	eTOKEN_BUFF,
	eTOKEN_DEBUFF,
	eTOKEN_EQUIPITEM,
	eTOKEN_TIMETYPE,
	eTOKEN_TIME,
	eTOKEN_MAPCHANGEPOS,
	eTOKEN_MONSTER,
	eTOKEN_MONSTERTIME, 

	eTOKEN_EXP,
	eTOKEN_SXP,
	eTOKEN_MONEY,
	eTOKEN_SKILLPOINT,
	eTOKEN_ITEM,
	eTOKEN_CHANGEJOB,
	eTOKEN_FORCETYPE,
	eTOKEN_GIVETITLE,

	/// 트리거 이벤트 관련
	eTOKEN_TRIGGER,
	eTOKEN_TE_LEVEL,
	eTOKEN_TE_RACE,
	eTOKEN_TE_JOB,
	eTOKEN_TE_HAVEITEM,
	eTOKEN_TE_LINKQUEST,
	eTOKEN_TE_SKILL,

	eTOKEN_HUMAN,
	eTOKEN_ELF,
	eTOKEN_BEAST,

	eTOKEN_TRUE,
	eTOKEN_FALSE,
};

/// 퀘스트 스크립트 어휘 분석기
class cQuestLexer : public cLexer
{
public:
	cQuestLexer( const char* buffer, unsigned int size );
};
