/* ==========================================================================
* 파    일 : UIManager.h
* 목    적 : 
* 작 성 자 : 이순규
* 작 성 일 : 2006.09.25
* 주의사항 : 
*===========================================================================*/
#pragma once

#include "UIEvent.h"
#include "UISkin.h"
#include "UIProperty.h"
#include "UIRect.h"
#include "BaseStage.h"
#include "IndexGenerator.h"

#include "Item_Common.h"

const unsigned int MAXEDIT_DEFAULTLENGTH = 8;

class cUINode;
class cUIContainer;
class cUIRootNode;
class cUIWindow;
class cUICursor;
class cUIIDList;
class cUIText;
class cUIImageFont;
class cUIFuncText;
class cUIFuncTextNode;
class cUINpcTelling;
class cMsgBox;
class cDragWindow;
class cApplication;
class cIconParam;
class cIcon;
class cUIRoundGauge;
class cPage;
struct sSceneData;

class cTipWindow;
class cItemTipWindow;
class cSkillTipWindow;
class cBuffToolTipWindow;
class cSimpleTipWindow;
class cChatTipWindow;

enum eMSGBox_Event;
enum eBoxSkin_Type;
enum eDragFrom;
enum eTip_Kind;
enum eNpcFunc;


/// UI 관리자
class cUIManager
{
	friend class cApplication;
	static cUIManager* mpSingleton;

public:
	cUIManager();
	~cUIManager();

	/// 초기화
	void SetCurrentStage( eSTAGE stageIndex );
	bool InitSkin( const cString& pathName );
	bool InitImageFont();
	bool InitIcon();
	bool InitNpc();

	/// 리셋
	void Reset();

	/// 최상위로 올라가야하는 Node를 등록한다.
	void GotoFrontNode( cUINode* node );
	void RemoveFrontNode( unsigned long frontId );

	/// 메세지박스들을 맨앞으로 보낸다
	void GotoFrontMsgBox();

	/// 윈도우 닫기 ( ESC 버튼 )
	bool Close();
	void NetUnLockAllUI();
	
	/// 스킨 체인지
	void ChangeSkin( const cString& pathName );

	/// 업데이트
	void Process( unsigned long deltaTime, unsigned long accumTime );
	void Render();

	/// 모달 윈도우
	bool SetModal( cUIWindow* window );
	void ReleaseModal( cUIWindow* window );

	/// 메시지박스 ( 이벤트 넘, 스킨플래그, 모달타입, 제한시간, 제한시간 출력, sucess = 제한시간후 send할 메세지 타입(성공,실패) )
	bool CreateModal( eSTAGE handlerIndex, eMSGBox_Event eventtype, LPCTSTR text, LPCTSTR captiontext, eBoxSkin_Type skintype, void* extraData = 0,
					  unsigned long totaltime = 0, bool printTime = false, bool success = false, unsigned int maxLen = MAXEDIT_DEFAULTLENGTH );
	void DestroyMsgBox( cMsgBox* pMsgBox );
	void CloseAllMsgBox( bool event );

	/// 메시지박스의 text를 체인지 한다.
	void ChangeModalMessage( LPCTSTR text );

	/// 임의로 모달박스를 제거한다.
	void SendEventToMsgbox( bool success, eMSGBox_Event eventtype );	/// 정해진 이벤트를 가진 모달 닫기
	void ModalEventFromGameSystem( bool success );						/// 맨위에 있는 모달 닫기
	void CloseMsgBox( eMSGBox_Event eventtype );						/// 해당 이벤트를 가진 모달을 닫는다

	/// 사용자로부터 이벤트를 통지
	bool PostEventFromUser( const cUIEvent& event );

	/// 새로운 윈도우 show 시 리셋할 데이터처리
	void CheckEventNode( cUINode* n );

	/// 마우스 캡쳐 노드를 설정 및 해제
	void SetCaptureNode( cUINode* node );
	void ReleaseCaptureNode( cUINode* node );

	/// 호버노드 해제
	void ReleaseHoverNode( cUINode* node );

	/// 포커스 노드를 설정 및 해제
	void SetFocusedNode( cUINode* node );
	void ReleaseFocusedNode( cUINode* node );

	/// 마우스 이벤트 받는 노드 초기화( 호버, 캡쳐 )
	void ReleaseEventNode();

	/// 현재 등록된 포커스 노드를 강제 제거한다.
	void ClearFocusedNode();

	/// 팁
	void ShowItemTip( eTip_Kind tipkind, const cUIPos& pos, unsigned long itemIndex, int slotIndex, cUIRoundGauge* gauge );
	void ShowItemTip( eTip_Kind tipkind, const cUIPos& pos, unsigned long itemIndex, unsigned int enhance );
	void ShowOtherItemTip( eTip_Kind tipkind, const cUIPos& pos, sInventory& inven );
	void ShowSkillTip( eTip_Kind tipkind, cSkillTipWindow* pTip, const cUIPos& pos, unsigned long skillIdx, char stepIdx, bool store );
	void ShowBuffTip( cBuffToolTipWindow* pTip, const cUIPos& pos, unsigned long uniqueIdx, unsigned long influenceIdx, bool showTime = true );
	void ShowCommunityTip( cSimpleTipWindow* pTip, const cUIPos& pos, cStringT str );
	void ShowChatItemTip( const cUIPos& pos, sInventory& inven );
	void ShowChatItemTip( const cUIPos& pos, unsigned long itemIndex, int slotIndex );
	void ShowUITip( const cUIPos& pos, unsigned long tipIdx );
	void HideTip();

	/// 드래그 윈도우
    void SetDragWindow( cDragWindow* dragWindow );
	void ShowDrag( cUIWindow* pcaller, eDragFrom dragFrom, cIcon* icon, const cUIPos& pos, bool shift );
	void HideDrag( cUIWindow* pcaller );
	bool IsVisibleDrag();

	/// NPC 배경 윈도우
	void SetNpcBackWindow( cUIWindow* back );
	cUIWindow* GetNpcBackWindow() { return mpNpcBackWindow; }
	bool IsShowNpcBack();
	void ShowNpcBack();
	void HideNpcBack();
	void HideNpcBackNoMsg();

	void SetNpcFunc( eNpcFunc npcType );
	eNpcFunc GetNpcFunc();
	
	/// 윈도우 show 예약
	void SetRestoreShow( cUIWindow* n );

	/// 특별한 윈도우들의 show 복구 ( npc 창 닫았을시 )
	void RestoreShow();

	/// 자기 자신이 아닌 다른 윈도우가 마우스 클릭 이벤트 받는경우 통지 메세지 발생
	void AddEventOtherClick( cUIWindow* win );

	/// 채팅 아이템 팁 윈도우
	void SetChatItemTipWindow( cChatTipWindow* win );

	/// 현재 스킨을 리턴
	cUISkin* GetSkin() const;

	/// 속성을 리턴 
	cUIProperty* GetProperty() const;

	/// UI ID 리스트 포인터 리턴
	cUIIDList* GetUIIDList() const;

	/// 루트 노드를 리턴
	cUIRootNode* GetRootNode() const;

	/// 호버 노드를 리턴 
	cUINode* GetHoverNode() const;

	/// 마우스 캡쳐 노드를 리턴
	cUINode* GetCaptureNode() const;

	/// 포커스 노드를 리턴
	cUINode* GetFocusedNode() const;

	/// 부모가 root인 컨테이너 리턴 
	cUIContainer* GetContainer( unsigned int id );
	cUIWindow* GetModalBox() { return mpModalMsgBox; }

	/// 가장가까운 컨테이너 리턴 
	cUIContainer* UpdateNearContainer( cUIContainer* con, bool axisX ) const;

	LPCTSTR GetUIText( unsigned int textId );
	bool GetUIText( cStringT*, unsigned int textId );

	/// 이미지 폰트
	cUIImageFont* GetImageFont( unsigned int fontIndex );

	/// 아이콘
	cIconParam* GetIconParam( unsigned int iconId );

	/// Npc
	cUINpcTelling* GetNpcTelling( unsigned int npcId ) const;
	const cUIFuncTextNode* GetNpcTextNode( unsigned int textId );

	//void AddVisibleArr( cUINode* node, bool visible );

	/// page
	bool AddPage( unsigned long pageIdx, cPage* page );
	cPage* GetPage( unsigned long pageIdx );

	/// scene
	sSceneData* GetSceneData( unsigned long sceneIdx );

	bool IsCameraEnableContainUI();

protected:
	/// 로딩
	bool LoadIDList( const cString& pathName );
	bool LoadSkin( const cString& pathName );
	bool LoadProperty( const cString& pathName );
	bool LoadSkinText( const cString& pathName );

	/// 이미지 폰트
	bool LoadImageFonts( const cString& pathName );

	/// 아이콘
	bool LoadIconParams( const cString& pathName );

	/// Npc
	bool LoadNpcText( const cString& pathName );
	bool LoadNpcScripts( const cString& pathName );
	bool LoadNpcScript( const cString& pathName );
	bool LoadNpcScene( const cString& pathName );

	/// Reload 기능( 스킨스크립트 변경시 리로드 )
	bool ReloadSkin( const cString& pathName );

	/// 마우스 캡쳐 노드를 갱신
	void UpdateHoveredNode( cUIContainer* root, const cUIPos& pos );

	/// 자신이 아닌 다른 영역 클릭
	void EventOtherClick( const cUIPos& pos );

	void ShowTip();

	bool MsgBoxEventProcess( const cUIEvent& event );

	/// 최상위 등록 Node가 있으면 적용한다.
	void ApplyFrontNode( cUINode* node );

public:
	/// 단일체를 리턴
	static cUIManager* GetSingleton();

private:
	void UpdateScreenSize( unsigned int width, unsigned int height );

protected:
	/// 스킨
	cUISkin* mpSkin;
	/// 속성 
	cUIProperty* mpProperty;
	/// 텍스트
	cUIText* mpSkinText;
	/// UI ID 리스트 
	cUIIDList* mpIDList;
	/// 루트 노드
	cUIRootNode* mpRootNode;
	cUIRootNode* mpStageRootNode[eStage_Max];

	/// 마우스 캡쳐 노드
	cUINode* mpCaptureNode;
	/// 마우스 오버 노드
	cUINode* mpHoveredNode;
	/// 포커스 노드
	cUINode* mpFocusedNode;

	/// 모달 메시지 박스
	cUIWindow* mpModalMsgBox;

	/// 마우스 이벤트 발생시의 포지션값 저장 
	cUIPos	mMousePos;

	/// 팁
	cTipWindow* mTipWindow;

	/// 채팅 팁 윈도우
	cChatTipWindow* mChatItemTipWindow;

	/// 드래그윈도우
	cDragWindow* mpDragWindow;

	/// 이용중인 npc 타입
	eNpcFunc mNpcFuncType;

	/// NPC Back 윈도우
	cUIWindow* mpNpcBackWindow;
	
	/// 제거 되어질 MsgBox들에 대한 처리..
	typedef	tPointerList<void*> cDestroyMsgBoxList;
	cDestroyMsgBoxList	mDestroyMsgBoxList;

	typedef tPointerHashMap<unsigned long, void*> cApplyFrontMap;
	cApplyFrontMap						mApplyFrontMap;
	cIndexGenerator<unsigned long>		mFrontIdGen;

	/// 이미지 폰트
	typedef tHashMap<unsigned int, void*> cImageFontMap;
	cImageFontMap mImageFontMap;

	/// 아이콘
	typedef tHashMap<unsigned int, void*> cTextureMap;
	cTextureMap mIconTextureMap;

	typedef tHashMap<unsigned int, void*> cIconParamMap;
	cIconParamMap mIconParamMap;

	/// Npc
	cUIFuncText* mpNpcText;
	typedef tHashMap<unsigned int, void*> cNpcTellingMap;
	cNpcTellingMap mNpcTellingMap;

	/// 페이지 관리용 (페이지인덱스, 페이지 내용)
	typedef tPointerHashMap<unsigned long, void*> cPageMap;
	cPageMap mPageMap;

	/// 페이지 장면 이미지 스크립트
	typedef tPointerHashMap<unsigned long, void*> cSceneMap;
	cSceneMap mSceneMap;

	/// npc 윈도우가 끝나면 보여줘야할 윈도우 
	typedef tArray<void*> cRestoreShow;
	cRestoreShow mRestore;

	/// 메세지박스 관리용
	typedef tPointerList<void*> cMsgBoxList;
	cMsgBoxList	mMsgBoxList;

	/// eUIEVENT_MOUSE_OTHERCLICK 통지 메세지 보낼 UI 목록
	typedef tPointerList<void*> cOtherClickList;
	cOtherClickList	mOtherClickList;
};

inline void cUIManager::SetCurrentStage( eSTAGE i )
{
	mpRootNode = mpStageRootNode[i];
}

inline void cUIManager::SetDragWindow( cDragWindow* dragWindow )
{
	if( dragWindow )
		mpDragWindow = dragWindow;
}

inline void cUIManager::SetNpcBackWindow(cUIWindow* back )
{
	if( back )
		mpNpcBackWindow = back;
}

inline void cUIManager::SetNpcFunc( eNpcFunc npcType )
{
	mNpcFuncType = npcType;
}

inline eNpcFunc cUIManager::GetNpcFunc()
{
	return mNpcFuncType;
}

inline void cUIManager::SetChatItemTipWindow( cChatTipWindow* win )
{
	if( win )
		mChatItemTipWindow = win;
}

inline cUISkin* cUIManager::GetSkin() const
{
	return mpSkin;
}

inline cUIProperty* cUIManager::GetProperty() const
{
	return mpProperty;
}

inline cUIIDList* cUIManager::GetUIIDList() const
{
	return mpIDList;
}

inline cUIRootNode* cUIManager::GetRootNode() const
{
	return mpRootNode;
}

inline cUINode* cUIManager::GetHoverNode() const
{
	return mpHoveredNode;
}

inline cUINode* cUIManager::GetCaptureNode() const
{
	return mpCaptureNode;
}

inline cUINode* cUIManager::GetFocusedNode() const
{
	return mpFocusedNode;
}

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

#define UIMAN cUIManager::GetSingleton()
