#pragma once

#include <list>
#include <string>
//#include "../xml/xmlui.h"
#include "uiframe.h"
#include "uimodel.h"
#include "uibutton.h"
#include "uicheckbutton.h"
#include "uiradiobutton.h"
#include "uieditbox.h"
#include "uilistbox.h"
#include "uistatusbar.h"
#include "uislider.h"
#include "uimessageframe.h"
#include "uiscrollframe.h"
#include "uitooltip.h"

using namespace std;

class CXmlNode;
class CXmlLayout;
class CXmlFile;
class CXmlUi;
class CUi
{
public:
	CUi();
	virtual ~CUi();

	struct MouseKey
	{
		CUiFrame*	pFrame;
		float		time;
	};

	struct ltstr
	{
		bool operator () (const char* p1, const char* p2) const
		{
			return strcmp(p1, p2) < 0;
		}
	};

	void					Update(float elapsedTime, InputState &state);
	void					Render2D();
	void					Render3D();
	bool					MsgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
	
	void					SetScreenSize(CUiSize& size)		{ m_pRootFrame->SetSize(size); }
	void					SetScale(float scale);
	float					GetScale()							{ return m_scale; }
	CUiFrame*				GetRoot()							{ return m_pRootFrame; }
	void					SetCapture(CUiFrame* pUiFrame, int key);
	CUiFrame*				GetCapture()						{ return m_pCapture; }
	int						GetCaptureKey()						{ return m_captureKey; }
	void					LockKeyboard(CUiFrame* pUiFrame)	{ m_pKeyCapture = pUiFrame; }
	CUiFrame*				GetLockKeyboard()					{ return m_pKeyCapture; }
	void					SetDragFrame(CUiFrame* pUiFrame)	{ m_pDragFrame = pUiFrame; }
	CUiFrame*				GetDragFrame()						{ return m_pDragFrame; }
	CUiFrame*				GetMouseOver()						{ return m_pMouseOver; }
	CUiFrame*				GetMouseFocus()						{ return m_pMouseFocus; }
	void					OnReceiveDrag(CUiPoint& pt, CUiFrame* pExclude);
	void					SetMouseDown(int key, CUiFrame* pUiFrame);
	CUiFrame*				GetMouseDown(int key);
	lua_State*				GetLuaState()						{ return m_luaState; }	
	void					LoadScriptFile(const char* filename);
	void					LoadScript(const char* script);
	CUiInput*				GetUiInput()						{ return &m_input; }
	CUiFrame*				GetKeyboardFocus()					{ return m_pKeyboardFocus; }
	CUiPoint				GetCursorPos()						{ return m_cursorPos; }
	CUiPoint				GetCursorOffset()					{ return m_cursorOffset; }

	void					OpenTocFile(const char* filename, const char* resourcePath);
	void					BuildFrames();
	CUiLayout*				CreateObject(int type, const char* name, CUiLayout* pParent);
	CUiLayout*				FindObject(const char* name);
	void					RegisterEvent(const char* event, CUiFrame* pUiFrame);
	void					UnregisterEvent(const char* event, CUiFrame* pUiFrame);
	bool					SendEvent(const char* event);

protected:
	friend class CUiLayout;	
	void					InsertObject(CUiLayout* layout);
	void					DeleteObject(CUiLayout* layout);

	void					LoadXmlFile(CXmlFile* pXmlFile);
	void					LoadXmlScript(CXmlNode* pXmlNode);
	CUiFrame*				LoadXmlFrames(CUiLayout* pUiParent, CXmlLayout* pXmlLayout);
	CUiLayout*				LoadXmlLayers(CUiLayout* pUiParent, CXmlLayout* pXmlLayout);
	void					LoadXmlLayout(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);	
	void					LoadXmlFontString(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlTexture(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlFrame(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlModel(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlButton(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlCheckButton(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlRadioButton(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlSlider(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlStatusBar(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlEditBox(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlListBox(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlMessageFrame(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlScrollFrame(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);
	void					LoadXmlTooltip(CUiLayout* pUiLayout, CXmlLayout* pXmlLayout);

protected:
	//friend class CUiFrame;	
	map<const char*, CUiLayout*, ltstr>		m_object;
	map< string, vector<CUiFrame*> >		m_userEvent;	
	string					m_resourcePath;
	lua_State*				m_luaState;
	list<CUiFrame*>			m_lock;
	CUiInput				m_input;
	CUiFrame*				m_pRootFrame;
	CUiFrame*				m_pCapture;
	int						m_captureKey;
	CXmlUi*					m_xmlUi;
	CUiFrame*				m_pKeyboardFocus;
	CUiFrame*				m_pMouseFocus;
	CUiFrame*				m_pKeyCapture;
	CUiFrame*				m_pMouseOver;
	CUiFrame*				m_pDragFrame;
	CUiFrame*				m_mouseDown[MAX_MOUSE_BUTTON_NUM];
	CUiFrame*				m_lastmouseDown[MAX_MOUSE_BUTTON_NUM];
	float					m_mouseDownTime[MAX_MOUSE_BUTTON_NUM];
	float					m_lastmouseDownTime[MAX_MOUSE_BUTTON_NUM];
	float					m_elapsedTime;
	float					m_absoluteTime;
	float					m_scale;
	CUiPoint				m_cursorPos;
	CUiPoint				m_cursorOffset;
};

extern lua_State*			g_uiLuaState;