#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_MODAL_OVERLAY_H_
#define __TOOLS_MODAL_OVERLAY_H_

#include "Core/Asura_String.h"

class Asura_Vector_2;
class Asura_Overlay;
class Asura_TreeDialog_Item;
class Asura_TreeDialog_Tree;
class Asura_TreeDialog_FileTree;

/////////////////////////////////////////////////////////////////////////////////////////
//base class for handling modal overlays
class Tools_Modal_Overlay
{
	public :
		Tools_Modal_Overlay(const Asura_String& xTitle);
		virtual ~Tools_Modal_Overlay(){};

		void ShowOverlay();//runs the overlay.. should only be used outside of rendering

		void RebuildOverlay();//deletes overlay and creates it again

		//Allows a standard overlay that has already been created and submitted to be run as a modal overlay.
		static void DoModal(Asura_Overlay* pxOverlay);

		static bool IsActive() { return s_bActive; }

	protected :
		class Asura_Overlay* GetOverlay();
		virtual void Update(){};

		void CloseOverlay();

		virtual void InitialiseOverlay(class Asura_Overlay* Overlay) = 0;

	private :
		static void DoModal(Tools_Modal_Overlay* pxModalOverlay,Asura_Overlay* pxAsuraOverlay);

		int m_iID;
		Asura_String m_xTitle;

		static bool s_bActive;
};

/////////////////////////////////////////////////////////////////////////////////////////

//Base overlay for those that may need a multi-line title
class Tools_BaseMessage_Overlay : public Tools_Modal_Overlay
{
	public :
		Tools_BaseMessage_Overlay(const Asura_String& xText);

	protected :
		virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset) = 0;
	
		virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay);

	private :
		Asura_String m_xText;

};

/////////////////////////////////////////////////////////////////////////////////////////

//A basic overlay for getting a yes/no response to a question from the user 
class YesNo_Overlay : public Tools_BaseMessage_Overlay
{
	public :
		YesNo_Overlay(Asura_String xQuestion);
		bool DoModal();

	protected :
		virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);

	protected :
		//unfortunately this lot has to be static... but we should never end up
		//with more than 1 copy of the overlay in action at a time
		static void YesSelected(){ReturnValue = true;}
		static void NoSelected(){ReturnValue = false;}

		static bool ReturnValue;
};

bool ShowYesNoOverlay(const char* pszFormat,...);

/////////////////////////////////////////////////////////////////////////////////////////

//A basic overlay for getting a true/false response to a question from the user 
class TrueFalse_Overlay : public YesNo_Overlay
{
public :
    TrueFalse_Overlay(Asura_String xQuestion);

protected :
    virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);
};

/////////////////////////////////////////////////////////////////////////////////////////

//A basic overlay for getting a yes/no/cancel response to a question from the user 
class YesNoCancel_Overlay : public Tools_BaseMessage_Overlay
{
public :
	YesNoCancel_Overlay(Asura_String xQuestion);
	bool DoModal();
	bool GetResult();

protected :
	virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);

protected :
	//unfortunately this lot has to be static... but we should never end up
	//with more than 1 copy of the overlay in action at a time
	static void YesSelected()   {ReturnValue = true;}
	static void NoSelected()    {ReturnValue = false;}
	static void CancelSelected(){SuccessValue= false;}

	static bool ReturnValue;
	static bool SuccessValue;
};

/////////////////////////////////////////////////////////////////////////////////////////

//A basic overlay for getting a yes/no/cancel response to a question from the user 
class TrueFalseCancel_Overlay : public YesNoCancel_Overlay
{
public :
    TrueFalseCancel_Overlay(Asura_String xQuestion);

protected :
    virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);
};

/////////////////////////////////////////////////////////////////////////////////////////

//Similar but with 4 options , Yes All , Yes , No  , No All.
//Returns true if one of the yes options is chosen.
//Use AllSelected() to find out if one of the all options was chosen
class YesNoAll_Overlay : public Tools_BaseMessage_Overlay
{
	public :
		YesNoAll_Overlay(Asura_String xQuestion);
		virtual bool DoModal();

		//true if 'yes all' or 'no all' chosen
		bool AllSelected(){return m_bAll;}

	protected :
		virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);

	private :
		static void _YesSelected(){s_pxThis->YesSelected();}
		static void _YesAllSelected(){s_pxThis->YesAllSelected();}
		static void _NoSelected(){s_pxThis->NoSelected();}
		static void _NoAllSelected(){s_pxThis->NoAllSelected();}

		void YesSelected(){m_bReturnValue = true;}
		void YesAllSelected(){m_bReturnValue = true;m_bAll = true;}
		void NoSelected(){m_bReturnValue = false;}
		void NoAllSelected(){m_bReturnValue = false;m_bAll = true;}

		bool m_bReturnValue;
		bool m_bAll;

		static YesNoAll_Overlay* s_pxThis;

};


/////////////////////////////////////////////////////////////////////////////////////////

class Message_Overlay : public Tools_BaseMessage_Overlay
{
	public :
		Message_Overlay(Asura_String xTitle);
		void DoModal();

	protected :
		virtual void InitialiseOverlay(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset);

};

void ShowMessageOverlay(const char* pszFormat,...);

/////////////////////////////////////////////////////////////////////////////////////////

//overlay for getting a string from the user
class GetString_Overlay : public Tools_Modal_Overlay
{
	public :
		GetString_Overlay(Asura_String _Title,const char* InitialString,int iMaxLength = 40);
		void DisableCancel(){m_bDisableCancel = true;}

		bool DoModal();

		char* GetString();
		const Asura_String& GetAsuraString() { return String; }

	protected:
		virtual void InitialiseOverlay(class Asura_Overlay* Overlay);

	private :
		virtual void Update();

		Asura_String String;
		int m_iMaxLength;
		bool m_bInputDebounced;
		bool m_bDisableCancel;

		//unfortunately this lot has to be static... but we should never end up
		//with more than 1 copy of the overlay in action at a time
		static void OkaySelected(){ReturnValue = true;}
		static void CancelSelected(){ReturnValue = false;}

		static bool ReturnValue;
};


/////////////////////////////////////////////////////////////////////////////////////////

//overlay for getting a number from the user
class GetNumber_Overlay : public Tools_Modal_Overlay
{
	public :
		GetNumber_Overlay(Asura_String title,float initialValue,float min,float max,const char* pszFormat = 0);
		bool DoModal();
	
		float GetNumber(){return Value;}

	protected:
		virtual void InitialiseOverlay(class Asura_Overlay* Overlay);

	private :
		virtual void Update();

		float Value;
		float Min;
		float Max;
		Asura_String m_xFormat;
		bool m_bInputDebounced;

		//unfortunately this lot has to be static... but we should never end up
		//with more than 1 copy of the overlay in action at a time
		static void OkaySelected(){ReturnValue = true;}
		static void CancelSelected(){ReturnValue = false;}

		static bool ReturnValue;
};

/////////////////////////////////////////////////////////////////////////////////////////

//overlay for getting a number from the user
class GetIntNumber_Overlay : public Tools_Modal_Overlay
{
	public :
		GetIntNumber_Overlay(Asura_String title,int initialValue,int min,int max);
		bool DoModal();
	
		int GetNumber(){return Value;}

	protected:
		virtual void InitialiseOverlay(class Asura_Overlay* Overlay);

	private :
		virtual void Update();

		int Value;
		int Min;
		int Max;
		bool m_bInputDebounced;

		//unfortunately this lot has to be static... but we should never end up
		//with more than 1 copy of the overlay in action at a time
		static void OkaySelected(){ReturnValue = true;}
		static void CancelSelected(){ReturnValue = false;}

		static bool ReturnValue;
};

/////////////////////////////////////////////////////////////////////////////////////////

// overlay for getting flags from the user
class GetFlags_Overlay : public Tools_Modal_Overlay
{
public:
    GetFlags_Overlay( const Asura_String& xTitle );
    virtual ~GetFlags_Overlay();

    void  AddItem( const char* pszName, int iFlagBit );
    bool  DoModal();
    u_int GetFlags() const { return m_uFlags; }

protected:
	virtual void InitialiseOverlay( class Asura_Overlay* pxOverlay );

private:

    static void OkaySelected()   { s_bReturnValue = true;  }
    static void CancelSelected() { s_bReturnValue = false; }

private:
    struct NameFlagBit
    {
        const char*  m_pszName;
        int          m_iFlagBit;
        NameFlagBit* m_pxNext;

        NameFlagBit( const char* pszName, int iFlagBit )
        : m_pszName( pszName ), m_iFlagBit( iFlagBit ), m_pxNext( NULL )
        {}
    }*    m_pxNameFlagBits;
    u_int m_uFlags;

    static bool s_bReturnValue;
};

/////////////////////////////////////////////////////////////////////////////////////////

#include "list_tem.hpp"

struct ListSelectionItem
{
	Asura_String xString;
	Asura_String xHelpString;
	int          iData;
	bool         bSelectedInitially;
	bool         bHidden;
	bool         bTicked;
};

class ListSelection_Overlay : public Tools_Modal_Overlay
{

	public:

		ListSelection_Overlay( const Asura_String& xTitle );
		virtual ~ListSelection_Overlay( void );

		// function to clear it out so we can start again
		void Reset( void );

		void AddItem( const char* szString, int iData = 0, bool bIsSelectedInitially = false, const char* szHelpString = NULL, bool bDontAddIfDuplicateString = false );
		virtual bool DoModal( void );

        bool HasSelectedItem( void ) const { return( m_iSelection >= 0 ); }
		const char* GetSelectionString( void ) const;
		int GetSelectionData( void ) const;

        bool Contains( int iData ) const;
        int GetNumItems( void ) const { return m_xItems.size(); }

		//Determines if list is sorted (defaults to true).
		//Needs to be done before any items are added to work.
		void SetSortList(bool bSort){m_bSort = bSort;}

		//Sets the item with the matching data to be the initial selection
		void SetInitialSelection(int iData);
		void SetInitialSelection(const Asura_String& xString);

		//Functions for tickbox list variation

		//Initialise ticked status by data/name
		void SetItemTicked(int iData,bool bTicked);
		void SetItemTicked(const char* pszName,bool bTicked);

		//Get name/data/ticked status by index. (the index number won't
		//correspond to the order in which items were added)
		const char* GetItemName(int iIndex) const;
		int GetItemData(int iIndex) const;
		bool GetItemTicked(int iIndex) const;

		const char* GetItemNameByData( int iData ) const;

	protected:

        virtual void AddExtraOverlayControls(class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset){};
        virtual const char* GetCancelButtonText( void ) const;
        virtual const char* GetEmptyListString( void ) const;
        virtual const char* GetOKButtonText( void ) const;

		virtual const char* GetListHeadingText() const {return 0;}

		//overridables for tickbox list overlay
		virtual bool IsTickboxList() const {return false;}
		virtual const char* GetTickAllButtonText() const {return "Tick All";}
		virtual const char* GetTickNoneButtonText() const {return "Tick None";}
		virtual const char* GetInvertButtonText() const {return "Invert";}

		// Make the list resizable?
		virtual bool IsListResizable() const { return false; }
		virtual Asura_Vector_2* GetResizableUserSize() const { return 0; }

		//selects the first item found that matches the passed data value
		bool SetSelectionByData( int iData );

		virtual void Update();

		//Causes ShouldItemBeHidden() to be called for each list item. The list overlay is then updated
		//to show just the items that should be visible
		void UpdateVisibilities();

        virtual bool ShouldItemBeHidden( const char* szString, int iData, bool bWasHidden ) { return bWasHidden; }

		virtual void InitialiseOverlay(class Asura_Overlay* Overlay);

	private:
		void UpdateStringList();

		List<ListSelectionItem*> m_xItems;
		const char**             m_ppcStrings;
		const char**			 m_ppcHelpStrings;
		int*                     m_piIndexConv;

		int m_iListSelection;

		int m_iSelection;
		int m_iNumLines;
		int m_iNumVisible;

		bool m_bSort;

		class Asura_Dialog* m_pxInputDialog;
		class Asura_List_Dialog * m_pxListDialog;

		float m_fInputTimer;
		char m_szInput[20];

        static void OkaySelected( void )   { s_bReturnValue = ( s_pxThis->m_iSelection >= 0 ); }
        static void CancelSelected( void ) { s_bReturnValue = false; }

		//functions for tickbox list buttons
		static bool _IsTicked(int iIndex,int iThis)
		{return ((ListSelection_Overlay*)iThis)->IsTicked(iIndex);}

		static void _ToggleTicked(int iIndex,int iThis)
		{((ListSelection_Overlay*)iThis)->ToggleTicked(iIndex);}

		static void _TickAll(int iThis)
		{((ListSelection_Overlay*)iThis)->TickAll();}

		static void _TickNone(int iThis)
		{((ListSelection_Overlay*)iThis)->TickNone();}

		static void _InvertTicks(int iThis)
		{((ListSelection_Overlay*)iThis)->InvertTicks();}

		static void _DoubleClicked(int iThis)
		{((ListSelection_Overlay*)iThis)->DoubleClicked();}


		bool IsTicked(int iIndex);
		void ToggleTicked(int iIndex);
		void TickAll();
		void TickNone();
		void InvertTicks();
		void DoubleClicked();



		static ListSelection_Overlay* s_pxThis;
		static bool                   s_bReturnValue;

};
// End class ListSelection_Overlay.

/////////////////////////////////////////////////////////////////////////////////////////

// Overlay for re-ordering a list of strings.
class OrderedListFunction
{
public:
	Asura_String m_xName;
	void(*m_pfnFunction)(void);
};

class ListOrdering_Overlay : public Tools_Modal_Overlay
{
public :
	ListOrdering_Overlay(const char* szTitle, int iNumStrings, const char** pszStrings, void** ppUserData = 0);
	~ListOrdering_Overlay();

	void AddFunction(const Asura_String xName, void(*pfnFunction)(void));
	bool DoModal();
	void Update();

protected:
	virtual void InitialiseOverlay(class Asura_Overlay*xOverlay);

private:
	void MoveCurrentSelectionUp();
	void MoveCurrentSelectionDown();
	void MoveCurrentSelectionTop();
	void MoveCurrentSelectionBottom();

	static void MoveUp(){s_pxThis->MoveCurrentSelectionUp();}
	static void MoveDown(){s_pxThis->MoveCurrentSelectionDown();}
	static void MoveTop(){s_pxThis->MoveCurrentSelectionTop();}
	static void MoveBottom(){s_pxThis->MoveCurrentSelectionBottom();}



	int m_iNumStrings;
	const char** m_pszStrings;
	void** m_ppUserData;

	const char** m_pszCancelStrings;//ordering to revert back to if cancedlled
	void** m_ppCancelUserData;

	int m_iSelection;

	List<OrderedListFunction*>m_xFunctionList;
	Asura_Overlay* m_pxOverlay;
	
	static void OkaySelected();
	static void CancelSelected();
	static bool s_bReturnValue;
	static ListOrdering_Overlay* s_pxThis;
};

//////////////////////////////////////////////////////////////////////////////
//
// TreeSelect_Overlay
// Provides a modal overlay for selecting from a tree.
//
//////////////////////////////////////////////////////////////////////////////

class TreeSelect_Overlay : public Tools_Modal_Overlay
{
public:
	// Public typedefs...
	typedef bool OkayEnabledFunction(int iUserData);

	// constructor/destructor
	TreeSelect_Overlay( const char* pszTitleString, const bool bAllowNone = false );
	//alternative constructor which makes use of an externally constructed tree
	TreeSelect_Overlay( const char* pszTitleString, Asura_TreeDialog_Tree* pxTree, const bool bAllowNone = false );
	virtual ~TreeSelect_Overlay();

	// overrides
	virtual void AddItem( const char* szItemName, const char* szParentName=NULL, int iItemData=0 );
	virtual bool DoModal();
	virtual void Update();
	
	// accessors
	const char*						GetSelection() const;
	int								GetSelectionData() const;
	Asura_Hash_ID					GetSelectionHash() const;
	const Asura_TreeDialog_Item*	GetSelectionItem() const;

	void	SetOkayEnabledFunction(OkayEnabledFunction* pfnOkayEnabled, int iUserData)	{ m_pfnOkayEnabled = pfnOkayEnabled, m_iOkayEnabledUserData = iUserData; }

protected:
	virtual void InitialiseOverlay( Asura_Overlay* pxOverlay );

	virtual void OnOkaySelected();
	virtual void OnCancelSelected();
	virtual void OnNoneSelected();
	virtual void OnSelectCurrentItem();

protected:
	bool							m_bReturnValue;
	const Asura_TreeDialog_Item*	m_pxSelectionItem;

	bool							m_bAllowNone;
	Asura_TreeDialog_Tree*			m_pxTree;
	bool							m_bOwnsTree;

	OkayEnabledFunction*			m_pfnOkayEnabled;
	int								m_iOkayEnabledUserData;

private:
	static void OkaySelected( int iUserData );
	static void CancelSelected( int iUserData );
	static void NoneSelected( int iUserData );
	static void SelectCurrentItem( int iUserData );
};


//////////////////////////////////////////////////////////////////////////////
//
// BlueprintSelect_Overlay
// Provides a modal overlay for selecting a blueprint.
//
//////////////////////////////////////////////////////////////////////////////

class BlueprintSelect_Overlay : public TreeSelect_Overlay
{
	typedef TreeSelect_Overlay PARENT;

public:
	BlueprintSelect_Overlay( const char* pszTitleString, Asura_Hash_ID* puBPSelection, Asura_Hash_ID* puTypeSelection, int iNumValidTypes = 0, const Asura_Hash_ID* puValidTypesArray = NULL, int iNumValidParents = 0, const Asura_Hash_ID* puValidParentsArray = NULL );

private:
	virtual void OnOkaySelected();		// This is called when ok button is pressed.
	virtual void OnSelectCurrentItem();	// This is called when doubleclick is pressed.

	bool UpdateBPHash();				// This function will update m_puBPHashID and m_puTypeHashID each time Ok or mouse double-click is pressed.

private:
	Asura_Hash_ID* m_puBPHashID;
	Asura_Hash_ID* m_puTypeHashID;
};


//////////////////////////////////////////////////////////////////////////////
//
// FileSelect_Overlay
// Provides a modal overlay for selecting a file from tree-list
//
//////////////////////////////////////////////////////////////////////////////

class FileSelect_Overlay : public TreeSelect_Overlay
{
public:
	FileSelect_Overlay( const char* pszTitleString, Asura_TreeDialog_FileTree* pxTree, const bool bAllowNone = true );
	FileSelect_Overlay( const char* pszTitleString, const char* pszDirectory, const char* pszFileExtension, const bool bAllowNone = true );

	// Call this function before DoModal to set current selection of the object. It can handle hash names with or without path.
	void SelectFile( Asura_Hash_ID uSelectedItemHashID, const bool bPathIsAddedInHash );

	// Call these functions when the DoModal is over. They will return user selection.
	void GetSelectedFile( Asura_Hash_ID& uSelectedItemHashID, Asura_String& xSelectedItemName );
	void GetSelectedFileWithPath( Asura_Hash_ID& uSelectedItemWithPathHashID, Asura_String& xSelectedItemWithPathName );


private:
	typedef TreeSelect_Overlay PARENT;

	static bool	IsSelectedTreeItemNotADir(int iUserData);
};


//////////////////////////////////////////////////////////////////////////////
//
// BlueprintTypeSelect_Overlay
// Provides a modal overlay for selecting a blueprint type.
//
//////////////////////////////////////////////////////////////////////////////

class BlueprintTypeSelect_Overlay : public ListSelection_Overlay
{
	typedef ListSelection_Overlay PARENT;

public:
	BlueprintTypeSelect_Overlay( const Asura_String& xTitle, Asura_Hash_ID& uTypeHashIDOut );

	virtual bool DoModal();

protected:
	virtual void InitialiseOverlay(class Asura_Overlay* Overlay);

private:
	Asura_Hash_ID& m_uTypeHashIDOut;
};


//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#endif //__TOOLS_MODAL_OVERLAY_H_
