// Tools_GUIMenu_Widget_Group.cpp
//
// Created by Richard Rice - 05/12/2006
// 
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "GUIMenu/Tools_GUIMenu_Widget_Group.h"

#ifdef ASURA_USE_GUI_MENU_SYSTEM
#include "GUIMenu/Asura_GUIMenu_System.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"

//#include "GUIMenu/Asura_GUIMenu_Widget_Base.h"
#include "GUIMenu/Asura_GUIMenu_Widget_Group.h"


#include "GUIMenu/Tools_Mode_GUIMenu.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------------------------**
** Tools_GUIMenu_PickItem_AddWidgetToGroup **
**-----------------------------------------*/

class Tools_GUIMenu_PickItem_AddWidgetToGroup : public Tools_GUIMenu_PickItem
{
public :
	Tools_GUIMenu_PickItem_AddWidgetToGroup(Tools_GUIMenu_Widget_Group* pxGroup)
	{
		m_pxGroup = pxGroup;
	}

	virtual const char* GetPrompt(){return "Select widget/element to add";}

	virtual bool IsValidSelection(Tools_GUIMenu_Root* pxItem)
	{
		if(pxItem)
		{
			if(pxItem == m_pxGroup) return false;
			//parent needs to be a menu page
			if(!pxItem->GetParent()) return false;
			return pxItem->GetParent()->GetType() == Asura_GUIMenu_Root::ASURA_GUIMENU_TYPEID_MENUPAGE;
		}
		return false;
	}

	virtual void OnFinish(Tools_GUIMenu_Root* pxItem)
	{
		if(pxItem)
		{
			m_pxGroup->AddWidget(pxItem);
		}
	}

private :
	Tools_GUIMenu_Widget_Group* m_pxGroup;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*-----------------------------------------**
** Tools_GUIMenu_PickItem_LinkToGroup **
**-----------------------------------------*/

class Tools_GUIMenu_PickItem_LinkToGroup : public Tools_GUIMenu_PickItem
{
public :
	Tools_GUIMenu_PickItem_LinkToGroup(Tools_GUIMenu_Widget_Group* pxGroup)
	{
		m_pxGroup = pxGroup;
	}

	virtual const char* GetPrompt(){return "Select a Group to link to";}

	virtual bool IsValidSelection(Tools_GUIMenu_Root* pxItem)
	{
		if(pxItem)
		{
			if(pxItem == m_pxGroup) return false;
			// It needs to be a group
			if(pxItem->GetType() != Asura_GUIMenu_Root::ASURA_GUIMENU_TYPEID_WIDGET_GROUP) return false;
			// Make sure we won't create a cycle of links
			if(m_pxGroup->CheckForCyclicLink(static_cast<Tools_GUIMenu_Widget_Group*>(pxItem))) return false;
			//parents need to be the same
			if(!pxItem->GetParent()) return false;
			return pxItem->GetParent() == m_pxGroup->GetParent();
		}
		return false;
	}

	virtual void OnFinish(Tools_GUIMenu_Root* pxItem)
	{
		if(pxItem)
		{
			m_pxGroup->LinkGroup(static_cast<Tools_GUIMenu_Widget_Group*>(pxItem));
		}
	}

private :
	Tools_GUIMenu_Widget_Group* m_pxGroup;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*----------------------------**
** Tools_GUIMenu_Widget_Group **
**----------------------------*/

Tools_GUIMenu_Widget_Group* Tools_GUIMenu_Widget_Group::s_pxSelectedGroup = 0;

Tools_GUIMenu_Widget_Group::Tools_GUIMenu_Widget_Group(Asura_GUIMenu_Widget_Group* pxAsuraGroup,Tools_GUIMenu_Root* pxToolsParent)
:Tools_GUIMenu_Widget_Base(pxAsuraGroup,pxToolsParent)
{
	m_pxAsuraGroup = pxAsuraGroup;
}

void Tools_GUIMenu_Widget_Group::OnSelection()
{
	s_pxSelectedGroup = this;
	PARENT::OnSelection();
}

void Tools_GUIMenu_Widget_Group::OnDeselection()
{
	s_pxSelectedGroup = 0;
	PARENT::OnDeselection();
}

void Tools_GUIMenu_Widget_Group::AddBasicOverlayControls(Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset)
{
	//skip the widget base controls , and go straight for the menu item base class
	Tools_GUIMenu_Root::AddBasicOverlayControls(pxOverlay,xOffset);
	xOffset.y += Asura_Dialog::SmallSpacing();
}

void Tools_GUIMenu_Widget_Group::AddOverlayControls(Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset)
{
	Tools_GUIMenu_Root::AddOverlayControls(pxOverlay,xOffset);
	xOffset.y += Asura_Dialog::SmallSpacing();

	Asura_Dialog* pxDialog;

	pxDialog = new Asura_Function_Dialog("Link to another group",xOffset,ChooseGroupToLink,(int)this);
	pxDialog->SetHelpText("Clamps this top left corner of this group to the bottom left of another");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::SmallSpacing();

	pxDialog = new Asura_Function_Dialog("Remove Link",xOffset,RemoveLink,(int)this);
	pxDialog->SetHelpText("Removes the link for this group");
	pxDialog->SetIsEnabledFunction(HasLinkedGroup,(int)this);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	pxDialog = new Asura_Function_Dialog("Add widget/element",xOffset,AddWidget,(int)this);
	pxDialog->SetHelpText("Adds an existing widget/element to this group..");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	//Controls for creating a new widget in the groups
	//Not sure it is worth taking up the space on the overlay for these , but they can be left for now I guess
	//RAR 21/05/2007
	#if 1
	pxDialog = new Asura_Dialog("Create Widget :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	for(int i=0;i<Tools_Mode_GUIMenu::GetInstance()->GetNumberOfWidgetTypes();i++)
	{
		int iType = Tools_Mode_GUIMenu::GetInstance()->GetWidgetType(i);
		const char* szName = Tools_Mode_GUIMenu::GetInstance()->GetWidgetTypeName(i);

		pxDialog = new Asura_Function_Dialog(szName,xOffset,CreateWidget,iType);
		pxDialog->SetHelpText("Create a new widget");
		pxDialog->SetIsEnabledFunction(CanCreateWidget);
		pxOverlay->AddDialog(pxDialog);
		xOffset.y+=Asura_Dialog::DefaultSpacing();
	}
	#endif
}

bool Tools_GUIMenu_Widget_Group::CanCreateWidget()
{
	if(!s_pxSelectedGroup) return false;
	return !s_pxSelectedGroup->GetAsuraData()->IsContainerFull();
}

void Tools_GUIMenu_Widget_Group::CreateWidget(int iType)
{
	if(!CanCreateWidget()) return;

	Tools_Mode_GUIMenu::GetInstance()->StartMenuItemPlacement(s_pxSelectedGroup,iType);
}

bool Tools_GUIMenu_Widget_Group::IsValidChildType(int iType) const
{
	//allow widgets
	return iType >= Asura_GUIMenu_Root::ASURA_GUIMENU_TYPEID_WIDGET_BEGIN && iType <=Asura_GUIMenu_Root::ASURA_GUIMENU_TYPEID_WIDGET_END;
}

bool Tools_GUIMenu_Widget_Group::CheckForCyclicLink(Tools_GUIMenu_Widget_Group *pxGroup)
{
	return m_pxAsuraGroup->CheckForCyclicLink(pxGroup->GetAsuraGroupID());
}

Asura_Hash_ID Tools_GUIMenu_Widget_Group::GetAsuraGroupID()
{
	return m_pxAsuraGroup->GetID();
}

bool Tools_GUIMenu_Widget_Group::HasLinkedGroup()
{
	return (m_pxAsuraGroup->GetLinkedGroup() != ASURA_HASH_ID_UNSET);
}

void Tools_GUIMenu_Widget_Group::AddWidget()
{
	//prompt for item to add
	Tools_GUIMenu_PickItem_AddWidgetToGroup* pxPickItem = new Tools_GUIMenu_PickItem_AddWidgetToGroup(this);
	Tools_Mode_GUIMenu::GetInstance()->StartPromptedSelection(pxPickItem);
}

void Tools_GUIMenu_Widget_Group::ChooseGroupToLink()
{
	//prompt for group to link to
	Tools_GUIMenu_PickItem_LinkToGroup* pxPickItem = new Tools_GUIMenu_PickItem_LinkToGroup(this);
	Tools_Mode_GUIMenu::GetInstance()->StartPromptedSelection(pxPickItem);
}

void Tools_GUIMenu_Widget_Group::LinkGroup(Tools_GUIMenu_Widget_Group* pxGroup)
{
	m_pxAsuraGroup->SetLinkedGroup(pxGroup->GetAsuraGroupID());
}

void Tools_GUIMenu_Widget_Group::RemoveLink()
{
	m_pxAsuraGroup->RemoveLink();
}

void Tools_GUIMenu_Widget_Group::AddWidget(Tools_GUIMenu_Root* pxItem)
{
	Asura_Assert(pxItem,"");
	
	//make sure the item is in the same menu page (should always be the case with the current selection process)
	if(GetMenuPage() != pxItem->GetMenuPage()) return;

	//Attempt the move
	pxItem->ChangeParent(this);
}

void Tools_GUIMenu_Widget_Group::Update()
{
	PARENT::Update();

	Asura_Hash_ID uHash =  m_pxAsuraGroup->GetLinkedGroup();
	if(uHash)
	{
		Asura_GUIMenu_Root* pxGUIObject = Asura_GUIMenu_System::FindWidgetObjectByID(uHash);
		if(pxGUIObject)
		{
			// We want to set this object's Rect so that it's top left corner
			// is positioned by the bottom right corner of it's linked group
			Asura_Bounding_Rectangle xCurRect = m_pxAsuraGroup->GetScaledWorldBounds();
			Asura_Bounding_Rectangle xLinkedRect = pxGUIObject->GetScaledWorldBounds();

			Asura_Bounding_Rectangle xNewRect;
			xNewRect.MinX = xLinkedRect.MinX;
			xNewRect.MinY = xLinkedRect.MaxY;
			xNewRect.MaxX = xLinkedRect.MinX + (xCurRect.MaxX - xCurRect.MinX);
			xNewRect.MaxY = xLinkedRect.MaxY + (xCurRect.MaxY - xCurRect.MinY);
			
			u_int uDragFlags = 0;
			uDragFlags |= TOOLS_MENUS_DRAG_MOVE;
			MoveOrResizeRect(GetRectangle(), xNewRect,uDragFlags,true,false);
		}
		else
		{
			// The group no longer exists, so remove the link
			RemoveLink();
		}
	}
}

void Tools_GUIMenu_Widget_Group::ChangeParent(Tools_GUIMenu_Root* pxParent)
{
	// If this group is linked to something, remove the link
	if (HasLinkedGroup())
	{
		RemoveLink();
	}

	PARENT::ChangeParent(pxParent);
}

#endif //ASURA_USE_GUI_MENU_SYSTEM
