//
// Asura_Overlay.h
//
// Created by Kevin Lea - 12/06/2001 11:12:04
// 
// Copyright (C) 2001 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __ASURA_OVERLAY_H__
#define __ASURA_OVERLAY_H__

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura_Maths.h"
#include "Core/Asura_String.h"
#include "Interface/Asura_Overlay_System.h"

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_Dialog;
class Asura_Tabs_Dialog;
class Asura_Overlay_System;

class Tools_ContextMenu_Context;
class Tools_ContextMenu;

// C L A S S E S /////////////////////////////////////////////////////////////

//Flags for reasons why overlay may be hidden
#define ASURA_OVERLAY_HIDEFLAG_MODE 0x00000001 //Hidden by tools mode code.
#define ASURA_OVERLAY_HIDEFLAG_OBJECTSYSTEM 0x00000002 //Hidden by tools object system.

//values for minimised state
enum
{
	ASURA_OVERLAY_MINIMISED_NOTMINIMISED,//not minimised
	ASURA_OVERLAY_MINIMISED_ATBOTTOM,//minimised to the bottom of the screen
	ASURA_OVERLAY_MINIMISED_INPLACE,//minimised but left where it is
};

enum
{
	ASURA_OVERLAY_RESIZE_MINX = 0x00000001,
	ASURA_OVERLAY_RESIZE_MAXX = 0x00000002,
	ASURA_OVERLAY_RESIZE_MINY = 0x00000004,
	ASURA_OVERLAY_RESIZE_MAXY = 0x00000008,

	//used when creating the overlay so that resizable controls can update based on their initial size
	ASURA_OVERLAY_RESIZE_INITIAL = 0x00000010,

	ASURA_OVERLAY_RESIZE_HORIZONTAL = ASURA_OVERLAY_RESIZE_MINX|ASURA_OVERLAY_RESIZE_MAXX,
	ASURA_OVERLAY_RESIZE_VERTICAL = ASURA_OVERLAY_RESIZE_MINY|ASURA_OVERLAY_RESIZE_MAXY,
};

#define ASURA_OVERLAY_MAX_NESTED_TAB_DIALOG (4)

class Asura_Overlay
{
	public:

        // C O N S T R U C T O R S   /   D E S T R U C T O R S ///////////////
		
		Asura_Overlay( const char *name, bool alwaysOnTop, Asura_Vector_2* position = 0, bool* minimised = 0 );
		//alternative constructor to allow for the minimised state being something other than a bool
		Asura_Overlay( const char *name, bool alwaysOnTop, Asura_Vector_2* position, u_int* puMinimisedState);

		virtual ~Asura_Overlay( void );

        // M E T H O D S /////////////////////////////////////////////////////

		void AddDialog( Asura_Dialog* pxNewDialog, bool bAddedByTabDialog = false );

		//Sets a parent dialog that will deal with any AddDialog calls made to this overlay.
		//This is so that the various AddOverlayControl functions used in tools can have
		//their output redirected to a tab control instead.
		//Should be set to NULL once finished with the tab dialog , before moving onto another
		void SetCurrentParentDialog(Asura_Dialog* pxParentDialog);

		//As above but allows for nested tab dialogs
		void PushCurrentParentDialog(Asura_Dialog* pxParentDialog);
		void PopCurrentParentDialog();

		void RenderBackdrop( u_int uColour = 0x007f7f ) const;
		void Render(void);
		void Update(void);
		virtual void PerFrameUpdate(void);//Another update function.This one is called regardless of whether the overlay is the active one.


		bool HasCursorOnTop(void) const;
		bool HasCursorOverTitleBar() const;

		Asura_Dialog* GetDialog(int id);
		Asura_Dialog* GetDialog(const char* pszLabel);
		void UpdateDialogLabel(int id,const char* text);
		void UpdateDialogLabel(Asura_Dialog* dialog,const char* text);
		void CalculateOverlaySize();

		//renames the overlay
		void SetTitle(const char* szName); 

		//updates the overlay size to deal with controls that have changed size , and repositions
		//the 'windows' dialog as needed.
		void ResizeOverlay();

		//Inidicates that the overlay size needs to be updated. Will get done during the update
		void FlagForResize(){m_bNeedsResize = true;}

        void SetPosition( float fX, float fY, bool bInstant = false );
        void SetPosition( const Asura_Vector_2& xPos, bool bInstant = false ) { SetPosition( xPos.x, xPos.y, bInstant ); }

		bool IsCursorOverADialog() const;

		void TabForwards();//For moving input focus to next control that will accept it
		void TabBackwards();//For moving input focus to previous control that will accept it
		Asura_Dialog* GetCurrentFocusDialog();

		void SetOverrideOverlaysHiddenFlag(bool bFlag) { m_bOverrideOverlaysHiddenFlag = bFlag; }
		bool GetOverrideOverlaysHiddenFlag() { return m_bOverrideOverlaysHiddenFlag && (Asura_Overlay_System::GetHideOverlaysNestLevel() < 2); }

		void SetAlwaysFullBright(bool bEnable) {m_bAlwaysFullbright=bEnable;}

		//Deletes a single dialog from the overlay. (Won't automatically resize it)
		void DeleteSingleDialog(Asura_Dialog* pxDialog);

		//Used internally to deal with radio button style tickboxes
		void RadioButtonPressed(const class Asura_Gadget* pxPressedGadget);

		void SetMinimised(bool bMinimise,bool bInstant);

		bool IsMinimised() const {return m_uMinimisedState != ASURA_OVERLAY_MINIMISED_NOTMINIMISED;}
		bool IsMinimisedAtBottom() const {return m_uMinimisedState == ASURA_OVERLAY_MINIMISED_ATBOTTOM;}

		//update the external store of the minimised state based on the state of the overlay
		void UpdateExternalMinimisedState();


		//can be overriden to hide the overlay
		virtual bool IsHidden() const {return m_uHideFlags != 0 && !m_bAlwaysOnTop;}

		//Adds/removes flags for hiding the overlay. Overlay is hidden if any are set
		void SetHideFlag(u_int uFlags,bool bSet);

		//Adds menu items when the overlay is clicked on.
		//By default nothing happens unless a callback function has been provded for this
		void AddContextMenuItems(Tools_ContextMenu& xMenu, Tools_ContextMenu_Context& xContext);

		//Sets the function to use for populating the context menu
		void SetContextMenuCallback(void(*pfnAddContextMenuItems)(Tools_ContextMenu& xMenu, const Tools_ContextMenu_Context& xContext), void* pUserData);

		//Returns true if the overlay is closing as a result of the close gadget being used
		bool IsClosingByCloseGadget() const{return m_bClosedByCloseGadget;}

		bool IsClosing() const {return m_bShouldClose || m_bClosedByCloseGadget;}

		//This makes all the currently existing dialogs ,that were created after a resizable control, relative
		//to the bottom of that resizable control (unless already relative to something else).
		//This won't be suitable for all such overlays , but in most cases , because of the order in which
		//things are added , this will do the appropriate thing.
		void MakeDialogsRelativeToResizableDialog();

		//If set then resizing for any resizable dialogs is based on the cursor being on the boundary of the dialog
		void SetResizeUsingDialogBorder(bool bSet){m_bResizeUsingDialogBorder = bSet;}
		//If set then resizing for any resizable dialogs is based on the cursor being on the boundary of the overlay
		void SetResizeUsingOverlayBorder(bool bSet){m_bResizeUsingOverlayBorder = bSet;}

		//Starts resizing of a dialog. For use by the resize gadget.
		void StartResize(Asura_Dialog* pxDialogToResize, u_int uResizeFlags);

		//Changes the windows cursor based on the resize flags
		void SetResizeCursor(u_int uResizeFlags);

		//Used by the overlay system for determining which 'always on top' overlay is the most recent
		void SetSubmissionIndex(u_int uIndex) {m_uSubmissionIndex = uIndex;}
		u_int GetSubmissionIndex() const {return m_uSubmissionIndex;}
		void SetTieBreakIndex(u_int uIndex) {m_uTieBreakIndex = uIndex;}
		u_int GetTieBreakIndex() const {return m_uTieBreakIndex;}

		virtual bool DoesOverlayOverrideCutAndPasteKey() { return false; }
		virtual bool DoesOverlayOverrideDeleteKey() { return false; }

        // S T A T E /////////////////////////////////////////////////////////
        
		Asura_String m_xName;

		Asura_Vector_2 m_xOrigin;
		Asura_Vector_2 m_xPosition;
		Asura_Vector_2* m_pxPositionBackup;
		
		float m_fWidth;
		float m_fHeight;
		float m_fFullHeight;
		unsigned int m_uBrightness;

		bool m_bIsBeingDragged;
		u_int m_uMinimisedState;
		bool m_bShouldClose;
		bool m_bSortToFront;
		bool m_bSortToBack;
		bool m_bAlwaysOnTop;
		bool m_bOnPanel;//for overlays that are stuck together on a 'panel' at the bottom of the screen

		bool* m_pbExternalMinimisedFlag;
		u_int* m_puExternalMinimisedState;

		bool m_bDialogTookFocus;

		unsigned int m_uID;

  		Asura_Dialog* m_pxDialogList;

	protected:
		void Initialise(const char *szName, bool bAlwaysOnTop, Asura_Vector_2* pxPosition, bool* pbMinimised, u_int* puMinimisedState);

		//returns flags indicating which directions the overlay can be resized in
		u_int GetAllowedResizeFlags() const;

		//Used by the overlay system for determining whether the overlay shold be resized/moved
		void GetResizeFlagsForCursorPosition(u_int& uFlags, Asura_Dialog*& pxResizedDialog) const;
		void UpdateDragAndResizeState();

		void UpdateResize();

		int m_iMaxDialogPriority;

        // F R I E N D S /////////////////////////////////////////////////////

        friend Asura_Overlay_System;

        // S T A T E /////////////////////////////////////////////////////////

        bool m_bAlwaysFullbright; // Default: false.
        bool m_bCanBeMovedByUser; // Default: true.
        bool m_bHasWindowsDialog; // Default: true; set to false by overlay system if name is empty and there's no close or minimise gadget.
		bool m_bJustCreated; // True when the overlay is first created. Used to prevent it taking mouse input too early
		bool m_bClickedOnOverlay; // true if the mouse is currently held down , and was originally clicked while over the overlay
		bool m_bClosedByCloseGadget;//true if overlasy is bieng closed as a result on clicking on the 'X' symbol

		bool m_bNeedsResize;

		u_int m_uHideFlags;

		bool m_bResizeUsingDialogBorder;//If true then resizing will be done on the extents of the dialogs
		bool m_bResizeUsingOverlayBorder;//If true then resizing will be done on the extents of the overlay
		u_int m_uResizeFlags;//extents currently being resized
		Asura_Vector_2 m_xResizeDelta;
		Asura_Dialog* m_pxResizedDialog;//dialog being resized
		bool m_bOverrideOverlaysHiddenFlag;

		Asura_Dialog* m_pxTabFocusDialog;//For tracking control that most recently had input focus

		int m_iNumCurrentParentDialog;
		Asura_Dialog* m_apxCurrentParentDialog[ASURA_OVERLAY_MAX_NESTED_TAB_DIALOG];

		void (*m_pfnAddContextMenuItems)(Tools_ContextMenu& xMenu, const Tools_ContextMenu_Context& xContext);
		void* m_pAddContextMenuItems_UserData;

		u_int m_uSubmissionIndex;//index number indicating when this was submitted
		u_int m_uTieBreakIndex;//Used by the overlay system to help with sorting

};


#endif//__ASURA_OVERLAY_H__
