//
// Tool_MetaMusicZone_Editor.cpp
//
// Created by Richard Rice - 26/01/05
// 
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Sound/Tools_MetaMusicZone_Editor.h"

#include "Entity/Asura_StaticMessage_System.h"
#include "Entity/Triggers/Asura_ServerEntity_MetaMusicTrigger.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Dialog.h"
#include "Sound/Asura_MetaMusic_Zone.h"
#include "Sound/Asura_MetaMusic_System.h"

#include "Entity/Tools_Message_Editing.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Sound/Tools_Mode_MetaMusic.h"

Tools_MetaMusicZone_Editor* Tools_MetaMusicZone_Editor::s_pxThis;

Tools_MetaMusicZone_Editor::Tools_MetaMusicZone_Editor(class Asura_Zone_Controller* pxController)
:Tools_Zone_Editor(pxController)
{
	s_pxThis = this;
	m_bChanged = false;
	m_bNPCWarningShown = false;
}

Tools_MetaMusicZone_Editor::~Tools_MetaMusicZone_Editor()
{
	s_pxThis = 0;
}

void Tools_MetaMusicZone_Editor::SetModified()
{
	Tools_SaveAsura::SetSoundsModified();
}

void Tools_MetaMusicZone_Editor::Update()
{
	Tools_Zone_Editor::Update();

	Asura_MetaMusic_Zone* pxZone = (Asura_MetaMusic_Zone*) GetSelectedZone();
    if ( pxZone == NULL )
    {
        return;
    }

    if(m_bChanged)
	{
		//check for illegal combinations of flags.
		for(int i=0;i<2;i++)
		{
			Asura_MetaMusic_Zone_Trigger* pxTrigger = &pxZone->m_axTrigger[i];

			u_int uChangedFlags = pxTrigger->m_uTriggerFlags^m_uFlagsBackup[i];
			u_int uAddedFlags = uChangedFlags & pxTrigger->m_uTriggerFlags;
			u_int uNewFlags = pxTrigger->m_uTriggerFlags;

			const u_int uStateFlags = ASURA_METAMUSICTRIGGER_FLAG_AMBIENT|ASURA_METAMUSICTRIGGER_FLAG_TENSION|ASURA_METAMUSICTRIGGER_FLAG_ACTION;
			if(uChangedFlags & uStateFlags)
			{
				//make sure only one of ambient/tension/action is set
				uNewFlags &=~ uStateFlags; 
				if(uAddedFlags & ASURA_METAMUSICTRIGGER_FLAG_AMBIENT)
				{
					uNewFlags |= ASURA_METAMUSICTRIGGER_FLAG_AMBIENT;
				}
				else if(uAddedFlags & ASURA_METAMUSICTRIGGER_FLAG_TENSION)
				{
					uNewFlags |= ASURA_METAMUSICTRIGGER_FLAG_TENSION;
				}
				else if(uAddedFlags & ASURA_METAMUSICTRIGGER_FLAG_ACTION)
				{
					uNewFlags |= ASURA_METAMUSICTRIGGER_FLAG_ACTION;
				}
			}

			const u_int uTrackFlags = ASURA_METAMUSICTRIGGER_FLAG_CHANGETRACK|ASURA_METAMUSICTRIGGER_FLAG_RESTARTLASTTRACK;
			if(uChangedFlags & uTrackFlags)
			{
				//make sure only one of change track/restart track is set
				uNewFlags &=~ uTrackFlags; 
				if(uAddedFlags & ASURA_METAMUSICTRIGGER_FLAG_CHANGETRACK)
				{
					uNewFlags |= ASURA_METAMUSICTRIGGER_FLAG_CHANGETRACK;
				}
				else if(uAddedFlags & ASURA_METAMUSICTRIGGER_FLAG_RESTARTLASTTRACK)
				{
					uNewFlags |= ASURA_METAMUSICTRIGGER_FLAG_RESTARTLASTTRACK;
				}
			}
		
			//put back the corrected flags
			pxTrigger->m_uTriggerFlags = uNewFlags;
			m_uFlagsBackup[i] = uNewFlags;

		}

		SetModified();
		m_bChanged = false;
	}

	//warning if trigger 1 npcs is more than trigger 2
	if(pxZone->m_axTrigger[0].IsUsed() && pxZone->m_axTrigger[1].IsUsed() &&
	   pxZone->m_axTrigger[0].m_iNumNPCsToTrigger > pxZone->m_axTrigger[1].m_iNumNPCsToTrigger)
	{
		if(!m_bNPCWarningShown)
		{
			Tools_Timed_Message_System::AddMessage( Tools_Timed_Message_System::COLOUR_WARNING, "NPCs for trigger 1 is higher than that for trigger 2." );
			m_bNPCWarningShown = true;
		}
	}
	else
	{
		m_bNPCWarningShown = false;
	}
    
}


void Tools_MetaMusicZone_Editor::AddOverlayControls(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset)
{
	Tools_Zone_Editor::AddOverlayControls(pxOverlay,xOffset);

	//add option to finish editing
	Asura_Dialog* pxDialog = new Asura_Function_Dialog("End Zone Editing",xOffset,Tools_Mode_MetaMusic::_EndZoneEditing);
	pxDialog->SetHelpText("Closes zone editing overlays , and reopends standard meta music mode overlays.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
}

void Tools_MetaMusicZone_Editor::AddZoneOverlayControls(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset)
{
	// get zone that we are adding controls for
	Asura_MetaMusic_Zone* pxZone = (Asura_MetaMusic_Zone*) GetSelectedZone();
    if ( pxZone == NULL )
    {
        return;
    }

	m_bChanged = false;
	m_bNPCWarningShown = false;

	Asura_Dialog* pxDialog;

	static char* s_apszTabs[2] = {"Trigger 1","Trigger 2"};
	Asura_Tabs_Dialog* pxTabsDialog = new Asura_Tabs_Dialog(xOffset,s_apszTabs,2);
	pxOverlay->AddDialog(pxTabsDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	//redirect all subsequent dialogs to the tab dialog
	pxOverlay->SetCurrentParentDialog(pxTabsDialog);

	float fTabsStartY = xOffset.y;
	float fTabsEndY = xOffset.y;

	//add each trigger to a different tab
	for(int i=0;i<2;i++)
	{
		xOffset.y = fTabsStartY;
		pxTabsDialog->SelectTab(i);

		Asura_MetaMusic_Zone_Trigger* pxTrigger = &pxZone->m_axTrigger[i];
		m_uFlagsBackup[i] = pxTrigger->m_uTriggerFlags;

		pxDialog = new Asura_Numerical_Dialog( "Trigger Number Of Attacking NPCs", xOffset, &pxTrigger->m_iNumNPCsToTrigger, 0, 50, 1, "%d", &m_bChanged );
		pxDialog->SetHelpText( "The number of NPCs attacking that will trigger this zone.\nIf Trigger 2 is being used , then this value should be higher for trigger 2 than for trigger 1." );
		pxOverlay->AddDialog( pxDialog );
		xOffset.y += Asura_Dialog::DefaultSpacing();

    	pxDialog = new Asura_Numerical_Dialog( "Minimum Trigger Time", xOffset, &pxTrigger->m_fMinimumTime, 0.0f, 60.0f, 1.0f, "%.1f", &m_bChanged );
		pxDialog->SetHelpText( "The minimum time the change in meta music will take effect for." );
		pxOverlay->AddDialog( pxDialog );
		xOffset.y += Asura_Dialog::DefaultSpacing();

		pxDialog = new Asura_FlagTickbox_Dialog("Restart Last Track", xOffset, &pxTrigger->m_uTriggerFlags, ASURA_METAMUSICTRIGGER_FLAG_RESTARTLASTTRACK, &m_bChanged);
		pxDialog->SetHelpText("Restarts the most recently played track , if it has stopped.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

		pxDialog = new Asura_FlagTickbox_Dialog("Change Track", xOffset, &pxTrigger->m_uTriggerFlags, ASURA_METAMUSICTRIGGER_FLAG_CHANGETRACK, &m_bChanged);
		pxDialog->SetHelpText("If set then the meta music track will be changed to the one selected , or just stopped if none is selected.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

		//get text for music selection control
		char szText[100];
		if(pxTrigger->m_uTrackID == ASURA_HASH_ID_UNSET)
		{
			strcpy(szText,"Track : <Stop Music>");
		}
		else
		{
			const char* pszTrackName = GetTrackName(pxTrigger->m_uTrackID);
			Asura_PrintfToBfr(szText,"Track : %s",100,true,pszTrackName ? pszTrackName : "<Unknown>");
		}
		

		pxDialog = new Asura_Function_Dialog(szText,xOffset,_SelectMusicTrack,i);
		pxDialog->SetHelpText("Choose the track to play.\nAlso used for stopping music.");
		pxDialog->SetIsEnabledFunction(IsEnabled_SelectTrack,i);
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

		pxDialog = new Asura_FlagTickbox_Dialog("Change To Ambient", xOffset, &pxTrigger->m_uTriggerFlags, ASURA_METAMUSICTRIGGER_FLAG_AMBIENT, &m_bChanged);
		pxDialog->SetHelpText("Switch the currently playing meta music track to the ambient state.\nIf no track is playing , this does nothing.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

		pxDialog = new Asura_FlagTickbox_Dialog("Change To Tension", xOffset, &pxTrigger->m_uTriggerFlags, ASURA_METAMUSICTRIGGER_FLAG_TENSION, &m_bChanged);
		pxDialog->SetHelpText("Switch the currently playing meta music track to the tension state.\nIf no track is playing , this does nothing.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

		pxDialog = new Asura_FlagTickbox_Dialog("Change To Action", xOffset, &pxTrigger->m_uTriggerFlags, ASURA_METAMUSICTRIGGER_FLAG_ACTION, &m_bChanged);
		pxDialog->SetHelpText("Switch the currently playing meta music track to the action state.\nIf no track is playing , this does nothing.");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();

 
		if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;
	}
	//End of tabs
	pxOverlay->SetCurrentParentDialog(0);
	static u_int s_uSelectedTab = 0;
	pxTabsDialog->SetSelectedTabPointer(&s_uSelectedTab);
	xOffset.y = fTabsEndY + 1.0f;

	//active flag
	pxDialog = new Asura_FlagTickbox_Dialog("Active", xOffset, &pxZone->m_uMetaMusicFlags, ASURA_METAMUSICZONE_FLAG_ACTIVE, &m_bChanged);
	pxDialog->SetHelpText("Indicates whether the zone is initially active.\nThe player/camera is never considered to be in an inactive zone.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

}

const char* Tools_MetaMusicZone_Editor::GetTrackName( Asura_Hash_ID uTrackID ) const
{
	const Asura_MetaMusic_TrackIndex xTrack = Asura_MetaMusic_System::GetTrackIndexFromHash(uTrackID);
	if (xTrack.IsNull()) return 0;

	return Asura_MetaMusic_System::GetTrackName(xTrack);
}

void Tools_MetaMusicZone_Editor::SelectMusicTrack(int iTrigger)
{
	Asura_MetaMusic_Zone* pxZone = (Asura_MetaMusic_Zone*) GetSelectedZone();
    if ( pxZone == NULL )
    {
        Tools_Timed_Message_System::AddMessage( Tools_Timed_Message_System::COLOUR_ERROR, "Internal error." );
        return;
    }

	ListSelection_Overlay xOverlay("Select Meta Music Track");
	//add all the track names to the overlay
	for(int i=0;i<Asura_MetaMusic_System::GetNumberOfTracks();i++)
	{
		xOverlay.AddItem( Asura_MetaMusic_System::GetTrackName( i ),
                          static_cast< int >( Asura_MetaMusic_System::GetTrackHash( i ) ) );
	}

	//add option for stopping music
	xOverlay.AddItem( "<Stop Music>", ASURA_HASH_ID_UNSET );

	//show selection overlay
	if ( !xOverlay.DoModal() )
    {
        return;
    }

	Asura_MetaMusic_Zone_Trigger* pxTrigger = &pxZone->m_axTrigger[iTrigger];

	pxTrigger->m_uTrackID = (Asura_Hash_ID)xOverlay.GetSelectionData();

    SetModified();

    DeleteZoneOverlay();
    CreateZoneOverlay();
}

bool Tools_MetaMusicZone_Editor::IsEnabled_SelectTrack(int iTrigger)
{
	if(s_pxThis)
	{
		const Asura_MetaMusic_Zone* pxZone = (Asura_MetaMusic_Zone*) s_pxThis->GetSelectedZone();
    	if ( pxZone == NULL )
    	{
    	    Tools_Timed_Message_System::AddMessage( Tools_Timed_Message_System::COLOUR_ERROR, "Internal error." );
    	    return false;
    	}

		const Asura_MetaMusic_Zone_Trigger* pxTrigger = &pxZone->m_axTrigger[iTrigger];
		return (pxTrigger->m_uTriggerFlags & ASURA_METAMUSICTRIGGER_FLAG_CHANGETRACK) ? true : false;
	}
	return false;
}


void Tools_MetaMusicZone_Editor::ZoneMessage_AddOverlayControls(struct Asura_StaticMessage* pxMessage,class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset)
{
	Asura_MsgData_MetaMusic_Zone* pxData = (Asura_MsgData_MetaMusic_Zone*)pxMessage->m_pData;

	//get text for control
	char szText[200];
	Asura_PrintfToBfr(szText,"Zone : %s",200,true,Tools_Mode_MetaMusic::GetZoneNameFromID(pxData->m_uZoneID));

	Asura_Dialog* pxDialog = new Asura_Function_Dialog(szText,xOffset,SelectZoneForMessage,(int)pxData);
	pxDialog->SetHelpText("Select the zone to activate/deactivate");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
}

void Tools_MetaMusicZone_Editor::SelectZoneForMessage(int iData)
{
	Asura_MsgData_MetaMusic_Zone* pxData = (Asura_MsgData_MetaMusic_Zone*)iData;

	u_int uNewID = Tools_Mode_MetaMusic::SelectZone("Select zone to activate/deactivate",pxData->m_uZoneID);

	if(uNewID != pxData->m_uZoneID)
	{
		pxData->m_uZoneID = uNewID;
		Tools_Message_Editing::UpdateMessageOverlay();
	}
}
