//////////////////////////////////////////////////////////////////////////////////////////
//
//  FILE        :  Tools_Mode_Botanicals.cpp
//
//  Created by Dave Reed - 04/11/05
//
//  Copyright (C) 2005 Rebellion (Derby), All Rights Reserved.
//
//  Vegetation editing/painting
//
//////////////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifdef ASURA_USE_BOTANICALS

#include "Core/Asura_UserInput.h"
#include "Core/Asura_LOS.h"
#include "Core/Asura_Timers.h"

#include "Camera/Asura_Camera.h"

#include "Tools_Mode_Botanicals.h"
#include "Tools_Botanicals_Object.h"
#include "Tools_Overlays.h"

#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"
#include "Botanicals/Asura_Botanicals_TemplateManager.h"
#include "Botanicals/Asura_Botanicals_InstanceManager.h"
#include "Botanicals/Tools_Botanicals_Styles.h"

#include "Misc/Tools_Polygon_Selection.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Misc/Tools_LOS.h"
#include "Misc/Tools_Render_Options.h"
#include "Entity/Tools_Entity_Object.h"
#include "Objects/Tools_Object_System.h"

#include "Debugging/Asura_Logfile.h"

#include "Interface/Asura_Interface.h"
#include "Interface/Asura_CommandConsole.h"
#include "Interface/Asura_Menubar_System.h"
#include "Interface/Asura_Menubar.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Dialog.h"

#include "Tools_System.h"
#include "Load&Save/Tools_SaveAsura.h"


// Data for the overlays
Asura_Handle	Tools_Mode_Botanicals::s_iMenuHandle=ASURA_INVALID_HANDLE;
bool			Tools_Mode_Botanicals::s_bPaintOverlayOpen=false;
bool			Tools_Mode_Botanicals::s_bEditTemplatesOverlayOpen=false;
bool			Tools_Mode_Botanicals::s_bTemplateOverlayOpen=false;	

bool			Tools_Mode_Botanicals::s_bStaticObjectsVisible=false;	
bool			Tools_Mode_Botanicals::s_bStaticObjectsCreated=false;
bool			Tools_Mode_Botanicals::s_bShowStaticObjects=false;
bool			Tools_Mode_Botanicals::s_bHideBotanicals = false;
bool			Tools_Mode_Botanicals::s_bHideBotanicalsClicked = false;

bool            Tools_Mode_Botanicals::s_bShowBoundingVolumes = false;
bool            Tools_Mode_Botanicals::s_bCheckInstanceVisibility = true;

void Tools_Mode_Botanicals::Initialise(void)
{		
	Tools_Timed_Message_System::AddMessage(0x00ff00, "Switched to Botanicals Mode");

	// Create the overlays
	CreatePaintOverlay();	

	// Create the 'vegetation' item on the main menu
	s_iMenuHandle = Asura_Menubar_System::CreateMenuSection();
	Asura_Menubar_Title* pxTitle;
	pxTitle = Asura_Menubar_System::AddTitle(s_iMenuHandle,"Botanicals");
	pxTitle->AddItem("Painting", Tools_Mode_Botanicals::TogglePaintOverlay,Tools_Mode_Botanicals::PaintOverlayIsOn);
	pxTitle->AddItem("Edit Templates",Tools_Mode_Botanicals::ToggleEditTemplatesOverlay,Tools_Mode_Botanicals::EditTemplatesOverlayIsOn);

#if defined( ASURA_BOTANICALS_BGR_IN_EDIT)
	Asura_Direct3D_Botanicals_Game_Render::MakeDataSet( Asura_Botanicals_InstanceManager::GetInstanceList(), true);
	Asura_Botanicals_InstanceManager::ConnectToolObjectsToBGR();
#else
	Asura_Direct3D_Botanicals_Game_Render::ClearDataSet();
#endif

	// Create tools objects from any existing instances
	Asura_Botanicals_InstanceManager::ConvertToToolObjects();

	// Make sure we've got the shapes (inc. selection shapes) loaded
	Asura_Botanicals_TemplateManager::LoadResources();

	// Init static objects
	s_bStaticObjectsVisible=false;	
	s_bStaticObjectsCreated=false;
	s_bShowStaticObjects=false;
	
	s_bHideBotanicals = Tools_System::IsHideBotanicalsChecked();
}



void Tools_Mode_Botanicals::TogglePaintOverlay(void)
{
	if (!s_bPaintOverlayOpen)
	{
		CreatePaintOverlay();	
	}
	else
	{
		Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_PAINT);
		s_bPaintOverlayOpen=false;
	}
}


void Tools_Mode_Botanicals::EditTemplates(void)
{	
	if (!s_bEditTemplatesOverlayOpen)
	{
		DisablePainting();
		ToggleEditTemplatesOverlay();
	}
}
 

void Tools_Mode_Botanicals::ToggleEditTemplatesOverlay(void)
{
	if (!s_bEditTemplatesOverlayOpen)
	{
		CreateEditTemplatesOverlay();	
	}
	else
	{
		Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_EDITTEMPLATES);
		s_bEditTemplatesOverlayOpen=false;
	}
}


void Tools_Mode_Botanicals::ToggleTemplateOverlay(void)
{
	if (!s_bTemplateOverlayOpen)
	{
		CreateTemplateOverlay();
	}
	else
	{
		Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_TEMPLATE);
		s_bTemplateOverlayOpen=false;
	}
}




void Tools_Mode_Botanicals::Update(void)
{
	static bool  s_bWasRangeLimited=true;
	static float s_fPreviousRange=-1.0f;

	// Do we need to add or remove tools objects?
	Asura_Vector_3 xPos = *Asura_Camera::GetPosition();

#ifndef ASURA_BOTANICALS_KEEP_ALL_TOOLS_OBJECTS
	float fRange = 1000000.0f;
	
	if (Tools_Render_Options::IsBotanicalsRangeLimited())
	{
		fRange = Tools_Render_Options::GetBotanicalsRange();			
	}
	
	if (s_bWasRangeLimited!=Tools_Render_Options::IsBotanicalsRangeLimited() ||
		s_fPreviousRange!=Tools_Render_Options::GetBotanicalsRange())
	{
		s_bWasRangeLimited=Tools_Render_Options::IsBotanicalsRangeLimited();
		s_fPreviousRange=Tools_Render_Options::GetBotanicalsRange();

		// Force an update of the tool objects
		Asura_Botanicals_InstanceManager::UpdateToolsObjectSet(&xPos,fRange, true);
	}
	else
	{
		// Only update them if the camera has moved far enough
		Asura_Botanicals_InstanceManager::UpdateToolsObjectSet(&xPos,fRange, false);
	}
#endif

	// Mouse wheel resizes the spray volume
	if (s_bPaintingActive || s_bPaintingBrightness)
	{
		UpdatePainting();
	}

	if(s_bPaintOverlayOpen)	
	{
		UpdatePaintingUI();
	}
		
	
	if(!Asura_Overlay_System::OverlaysHaveKeyboardFocus())
	{
		if(!Asura_UserInput::KeyPressed(ASURA_KEYID_SHIFT) && 
			!Asura_UserInput::KeyPressed(ASURA_KEYID_CTRL) &&
			!Asura_UserInput::KeyPressed(ASURA_KEYID_ALT))
		{
			//'H' Hide/unhide botanicals
			if(Asura_UserInput::DebouncedKeyPressed('h'))
			{
				Tools_System::ToggleHideBotanicals();
			}
		}		

		
		if(s_bPaintOverlayOpen)
		{
			// 'P' Toggle painting
			if(Asura_UserInput::DebouncedKeyPressed('p'))
			{
				s_bPaintingActive = !s_bPaintingActive;		
			}

			// 'O' Toggle one-click mode
			if(Asura_UserInput::DebouncedKeyPressed('o'))
			{				
				s_bOneClickPlacement = !s_bOneClickPlacement;		
			}

			// Shortcuts to select template/style
			if(Asura_UserInput::DebouncedKeyPressed('t'))
			{
				ChangeActiveTemplate();
			}

			if(Asura_UserInput::DebouncedKeyPressed('y'))
			{
				ChangeActiveStyle();
			}
		
			if(Asura_UserInput::DebouncedKeyPressed('i'))
			{
				s_eAlignToTerrain = (Tools_Botanicals_AlignToTerrain)((int)s_eAlignToTerrain+1);
				if(s_eAlignToTerrain == TOOLS_BOTANICALS_ALIGN_NUMENTRY) s_eAlignToTerrain = TOOLS_BOTANICALS_ALIGN_OFF;
			}

			// Handle the delete function if in paint mode, as the standard controls 
			// are disabled
			if(Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_DEL))
			{
				Tools_Object_System::DestroyAllSelected();
			}
		}
	}

	//Update visibility of botanical objects to match visibilty of botanicals as a whole
	if(s_bHideBotanicalsClicked)
	{
		Tools_System::ToggleHideBotanicals();
		s_bHideBotanicalsClicked = false;
	}
	s_bHideBotanicals = Tools_System::IsHideBotanicalsChecked();
	
	// Escape key to deselect all
	if(Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_ESCAPE))
	{
		Tools_Object_System::DeselectAllObjects();
	}
	
	UpdateTemplateEditing();

	// If painting isn't active, allow normal selection/movement
	Tools_Object_System::EnableAllControls(!(s_bPaintingActive || s_bPaintingBrightness));		


	// Update 'show static objs' state
	UpdateStaticObjects(&s_bStaticObjectsVisible,&s_bStaticObjectsCreated,&s_bShowStaticObjects);	

	s_bJustChangedTemplate = false;

}


void Tools_Mode_Botanicals::RenderWorld_PostToneMap(void)
{
	// If we're in paint mode, update that, as long as we're not 
	// trying to use the UI
	if ((s_bPaintingActive || s_bPaintingBrightness) && !Asura_Interface::UsingMenusOrOverlays())
	{
		RenderPainting();
	}
	else
	{
		s_bButton1PressedForPaint = false;
		s_bButton2PressedForPaint = false;
	}
}


void Tools_Mode_Botanicals::PreShutdown( void )
{
	//make sure all objects flagged for merging into the environment have been
	Tools_Botanicals_Object::MergeObjectsIntoEnvironmentIfNeeded();
}

void Tools_Mode_Botanicals::Shutdown(void)
{
	// Switch out of paint mode, as it makes it very easy to mess things up
	// by accidentally spraying everywhere...
	s_bPaintingActive=false;
	s_bPaintingBrightness = false;

	// Store the tool objects in the instance manager	
	Asura_Botanicals_InstanceManager::ConvertFromToolObjects();

	// Remove all mode-specific objects
	Tools_Object_System::DeleteAllModeSpecific();
	Tools_Object_System::EnableAllControls(false);


	// Close our overlays
	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_PAINT);
	s_bPaintOverlayOpen=false;

	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_EDITTEMPLATES);
	s_bEditTemplatesOverlayOpen=false;

	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_BOTANICALS_TEMPLATE);
	s_bTemplateOverlayOpen=false;

	Tools_Botanicals_StyleManager::CloseEditStyleOverlay();

	// Free up some C strings we had to use for UI lists
	FreeStyleNameStrings();
	FreeTemplateNameStrings();

	// Remove our menu
	if(s_iMenuHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Menubar_System::DestroyMenuSection(s_iMenuHandle);
		s_iMenuHandle = ASURA_INVALID_HANDLE;
	}
	
	Asura_Direct3D_Botanicals_Game_Render::MakeDataSet( Asura_Botanicals_InstanceManager::GetInstanceList());
}


bool Tools_Mode_Botanicals::IsModified()
{
	return Tools_SaveAsura::IsBotanicalsModified();
}

void Tools_Mode_Botanicals::SetModifiedFlag(bool bValue)
{
	Tools_SaveAsura::SetBotanicalsModified(bValue);
}

void Tools_Mode_Botanicals::QuickSave(void)
{		
	// Save just this mode
	// Save main asura file as well if modified (in case of merging). RAR 17/03/2006
	PreSave();
	if(Tools_SaveAsura::IsMainFileModified()) Tools_SaveAsura::QuickSaveFile();
	Tools_SaveAsura::SaveBotanicals();
	PostSave();
}


void Tools_Mode_Botanicals::PreSave()
{		
	//make sure all objects flagged for merging into the environment have been
	Tools_Botanicals_Object::MergeObjectsIntoEnvironmentIfNeeded();

	Asura_Botanicals_InstanceManager::ConvertFromToolObjects();
}


void Tools_Mode_Botanicals::PostSave()
{		
	Asura_Botanicals_InstanceManager::ConvertToToolObjects();
}


void Tools_Mode_Botanicals::InitialiseMode( void)
{
}

void Tools_Mode_Botanicals::ShutdownMode( void)
{
}


// This is used by both the botanicals and carpet systems to enable the display 
// of static objects whilst editing.
void Tools_Mode_Botanicals::UpdateStaticObjects(bool *pbStaticObjectsVisible, bool *pbStaticObjectsCreated, bool *pbShowStaticObjects)
{	
	bool bNeedStaticObjects = *pbShowStaticObjects;
	//*pbStaticObjectsCreated = s_bStaticObjectsCreated;
	

	if(bNeedStaticObjects != *pbStaticObjectsCreated)
	{
		if(bNeedStaticObjects)
		{
			//create all the objects  , and start them off as invisible
			Tools_Entity_Object::CreateAllObjects();

			s_bStaticObjectsVisible = false;
			*pbStaticObjectsCreated = s_bStaticObjectsCreated = true;
		}		
	}

	if(!*pbStaticObjectsCreated) return;

	//now update visibility
	if(bNeedStaticObjects != *pbStaticObjectsVisible)
	{
		for(LIF<Tools_Object*> xObjectLIF(&Tools_Object_System::ObjectList);!xObjectLIF.done();xObjectLIF.next())
		{
			//Tools_Object_Type eType = static_cast<Tools_Object_Type>(xObjectLIF()->Type);
			if(bNeedStaticObjects)
			{
				xObjectLIF()->HiddenFlags &=~ ObjectHideFlag_Mode;
			}
			else
			{
				xObjectLIF()->HiddenFlags |= ObjectHideFlag_Mode;
			}
		}

		*pbStaticObjectsVisible = bNeedStaticObjects;		
	}


}




void Tools_Mode_Botanicals::AddCollisionMeshesToExportList( List<Asura_String>* pxList )
{
// Foliage collision meshes are stored in the state tables, so only available when dynamic botanicals are supported
#if defined( ASURA_BOTANICAL_SUPPORT_DYNAMIC_DATA)

	int iNumTemplates = Asura_Botanicals_TemplateManager::GetNumTemplates();

	for(int i=0; i<iNumTemplates; i++)
	{
		Asura_Botanicals_Template *pxTemplate = Asura_Botanicals_TemplateManager::GetTemplate(i);

		if (pxTemplate->pxBotanicalShape)
		{
			Tools_BotanicalShape *pxToolsShape = pxTemplate->pxBotanicalShape->GetToolsShape();		

			if (pxToolsShape)
			{			
				for( const Asura_ListElt< Tools_Botanical_StateTable1D>* pxItStateTable = pxToolsShape->m_xList_xStateTables1D.Front(); NULL != pxItStateTable; pxItStateTable = pxItStateTable->Next())
				{
					const Tools_Botanical_StateTable1D& xToolStateTable = pxItStateTable->Data();

					for( const Asura_ListElt< Tools_Botanical_StateTable1D_Section>* pxItSectionTable = xToolStateTable.m_xList_xSection.Front(); NULL != pxItSectionTable; pxItSectionTable = pxItSectionTable->Next())
					{
						const Tools_Botanical_StateTable1D_Section& xToolSectionTable = pxItSectionTable->Data();
						
						for( const Asura_ListElt< Tools_Botanical_StateTable1D_Section_VersionRange>* pxItVersionTable = xToolSectionTable.m_xList_xVersionRanges.Front(); NULL != pxItVersionTable; pxItVersionTable = pxItVersionTable->Next())
						{
							const Tools_Botanical_StateTable1D_Section_VersionRange& xToolVersionTable = pxItVersionTable->Data();		

							Tools_Level_Export::AddFileToExportList(*pxList, xToolVersionTable.m_xCollisionMeshName, true);
						}
					}
				}
			}
		}
	
	}
#endif

}

#endif // ASURA_USE_BOTANICALS
