//
// Tools_Mode_Module.cpp
//
// Created by Richard Rice - 21/03/2003
// 
// Copyright (C) 2003 Rebellion, All Rights Reserved.
//


#include "Core/Asura.h"
#include "Module/Tools_Mode_Module.h"


#include "Core/Asura_UserInput.h"
#include "Debugging/Asura_Assert.h"
#include "Interface/Asura_Menubar_System.h"
#include "Interface/Asura_Menubar.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Cursor.h"
#include "Mesh/Asura_Mesh.h"
#include "Mesh/Asura_Mesh_System.h"
#include "Mesh/Asura_Env.h"
#include "Mesh/Asura_Env_System.h"
#include "Rendering/Asura_Module.h"
#include "Rendering/Asura_Text_Output.h"


#include "Tools_Overlays.h"
#include "Lighting/Tools_LightSets.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Load&Save/Tools_ModeDataFile.h"
#include "Misc/Tools_Help.h"
#include "Misc/Tools_Module_Selection.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Misc/Tools_Render.h"


///////////////////////////////////////////////////////////////////////////////////////
/*--------------**
** Help Strings **
**--------------*/
static const char* g_aszModuleModeHelpStrings [] =
{
	"R :           Rename module under cursor",
	"F :           Apply the current flag",
	"Shift+F :     Remove the current flag",
	"Ctrl+Z :      Undo",
	"Ctrl+Y :      Redo",
	"< :           Undo",
	"> :           Redo",
	NULL
};
///////////////////////////////////////////////////////////////////////////////////////
static const int g_iNumberOfModuleFlags = 3;

static int g_aiModuleFlagValues[g_iNumberOfModuleFlags] =
{
	ASURA_MODULE_FLAG_SCENERY,
	ASURA_MODULE_FLAG_EXTERIOR,
	ASURA_MODULE_FLAG_NEVERCAMERAMODULE
};

static const char* g_aszModuleFlagFlagNames[g_iNumberOfModuleFlags] =
{
	"Scenery Module",
	"Exterior",
	"Never Camera Module",
};

static const char* g_aszModuleFlagHelpStrings[g_iNumberOfModuleFlags] =
{
	"If a module is flagged as being scenery then entities are never considered to be within it for module linking purposes. As a result , scenery modules do not require module linking data of their own , but they still get linked to other modules.",
	"If a module is flagged as exterior then entities are only considered to be within it if they aren't within any non-exterior modules."
	"The camera is never considered to be in this module for the purpose of working out which modules to link in , but objects within the module will be visible as normal if the module is visible.",
};

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

Tools_Mode_Module* Tools_Mode_Module::s_pxThis = 0;
u_int Tools_Mode_Module::s_uSelectedTab = 0;



Tools_Mode_Module::Tools_Mode_Module()
{
	Asura_Assert(!s_pxThis,"");
	s_pxThis = this;

	m_iMenuHandle = ASURA_INVALID_HANDLE;
	m_xModuleOverlayPosition.x = 3.0f;
	m_xModuleOverlayPosition.y = 28.0f;
	m_bModuleOverlayOpen = true;

	m_iCurrentFlagIndex = 0;
	m_uSelectedLightSets = 1;
	m_bReplaceLightSets = false;

	m_eSubMode = SUBMODE_MODULE_FLAGS;
	UpdateSubModeFromSelectedTab();
}

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


void Tools_Mode_Module::InitialiseMode()
{
	//load values from .dat file
	TransferModeData(TOOLSMODEDATAFILE_LOAD);


    //Initalise module selection
    Tools_Module_Selection::Activate();

	//create the menubar
	m_iMenuHandle = Asura_Menubar_System::CreateMenuSection();
	Asura_Menubar_Title* pxTitle;

	pxTitle = Asura_Menubar_System::AddTitle(m_iMenuHandle,"Overlays");
	pxTitle->AddItem("Mode",Tools_Mode_Module::ToggleModuleOverlay,Tools_Mode_Module::ModuleOverlayIsOn);
	pxTitle->AddItem("Selection",Tools_Module_Selection::ToggleSelectionOverlay,Tools_Module_Selection::SelectionOverlayIsOn);

	//create overlays
	CreateModuleOverlay();

	//add help
	Tools_Help::AddHelpTopic("Module Mode",g_aszModuleModeHelpStrings);

	m_xModuleUndo.Initialise();
}

void Tools_Mode_Module::ShutdownMode()
{
	m_xModuleUndo.Shutdown();

	//remove help
	Tools_Help::RemoveHelpTopic("Module Mode");

	//close overlays
	Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_MODE);

	//shutdown the menu
	if(m_iMenuHandle != ASURA_INVALID_HANDLE)
	{
		Asura_Menubar_System::DestroyMenuSection(m_iMenuHandle);
	}
 
    Tools_Module_Selection::Deactivate();

	//save values to .dat file
	TransferModeData(TOOLSMODEDATAFILE_SAVE);

}

void Tools_Mode_Module::TransferModeData(int iMode)
{
	//open the file
	Tools_ModeDataFile xFile("ModuleMode.dat",iMode);

	//tranfer the data
	//(none of these should be removed , and new data should go on the end, otherwise
	//the files will get screwed up)
	xFile.Transfer(m_xModuleOverlayPosition);
	xFile.Transfer(m_bModuleOverlayOpen);
}


bool Tools_Mode_Module::IsModified()
{
	return Tools_SaveAsura::IsMainFileModified() || Tools_SaveAsura::IsModuleLinkingModified() || Tools_SaveAsura::IsSoundsModified();
}

void Tools_Mode_Module::QuickSave()
{
	Tools_SaveAsura::QuickSaveFile();
	if(Tools_SaveAsura::IsModuleLinkingModified()) Tools_SaveAsura::SaveModuleLinking();
	if(Tools_SaveAsura::IsSoundsModified()) Tools_SaveAsura::SaveSounds();
}


void Tools_Mode_Module::Update()
{
	UpdateSubModeFromSelectedTab();

	//Flag the undo to start a new undo batch
	m_xModuleUndo.MarkUndoStart();

    Tools_Module_Selection::Update();

	//act upon keyboard input
	HandleKeyboard();

}

void Tools_Mode_Module::RenderWorld_PostToneMap()
{
	//highlight modules with current flag
	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();

	if(m_eSubMode == SUBMODE_MODULE_FLAGS)
	{
		int iFlagToCheck = g_aiModuleFlagValues[m_iCurrentFlagIndex];

		for(int i=0;i<Asura_Module_System::GetNumberOfModules();i++)
		{
			if(pxEnv->GetModuleFlags(i) & iFlagToCheck)
			{
				Tools_Render::RenderMeshOutline( i, 0xff00ff00 ); // Green.
			}	
		}
	}
	else if(m_eSubMode == SUBMODE_LIGHTSETS)
	{
		if(m_uSelectedLightSets)
		{
			for(int i=0;i<Asura_Module_System::GetNumberOfModules();i++)
			{
				u_int uModuleLightSets = pxEnv->GetLightSets(i) & Tools_LightSets::GetValidLightSets();
				
				u_int uMatchedLightSets = m_uSelectedLightSets & uModuleLightSets;
				if(uModuleLightSets == m_uSelectedLightSets)
				{
					//exact match
					Tools_Render::RenderMeshOutline( i, 0xff00ff00 ); // Green.
				}
				else if(uMatchedLightSets == m_uSelectedLightSets)
				{
					//The module has all the selected light sets, and some others
					Tools_Render::RenderMeshOutline( i, 0xffffff00);//yellow
				}
				else if(uMatchedLightSets)
				{
					//The module has some of the selected light sets
					Tools_Render::RenderMeshOutline( i, 0xff0000ff);//blue
				}
			}
		}
	}
    
	Tools_Module_Selection::Render();
}

void Tools_Mode_Module::RenderUI()
{
    //show information on module that the cursor is over
    
	int iModuleIndex = Tools_Module_Selection::GetHighlitModule();
	
	float x,y;
	
	if(iModuleIndex>=0)
	{
		const Asura_Mesh* pxModuleMesh = Asura_Module_System::GetMeshForModule( iModuleIndex );

		Asura_Cursor::GetScreenCoords(x,y);
		x++;
		y--;

		Asura_Text_Output::Print( x, y++, 0xff00ff00, 0, "%s", pxModuleMesh->Name.GetString() );
	}


	if(m_eSubMode == SUBMODE_MODULE_FLAGS)
	{
		if(iModuleIndex>=0)
		{
			//list flags for current module
			x = 1;
			y = 3;
			Asura_Text_Output::Print(x,y++,0xffffff00,0,"Current Flags :");
			x++;

			Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();
			u_int uFlags = pxEnv->GetModuleFlags(iModuleIndex);

			if(uFlags)
			{
				for(int i=0;i<g_iNumberOfModuleFlags;i++)
				{
					if(uFlags & g_aiModuleFlagValues[i])
					{
						Asura_Text_Output::Print(x,y++,0xff00ff00,0,"%s",g_aszModuleFlagFlagNames[i]);
					}
				}
			}
			else
			{
				Asura_Text_Output::Print(x,y++,0xff00ff00,0,"None");
			}
		}
	}
	else if(m_eSubMode == SUBMODE_LIGHTSETS)
	{
		//list light sets for current module
		x = 1;
		y = 3;
		Asura_Text_Output::Print(x,y++,0xffffff00,0,"Module Colours :");
		x++;
		Asura_Text_Output::Print(x,y++,0xff00ff00,0,"Exact match");
		Asura_Text_Output::Print(x,y++,0xffffff00,0,"Has all selected light sets");
		Asura_Text_Output::Print(x,y++,0xff0000ff,0,"Has some selected light sets");
		x--;
		y++;


		if(iModuleIndex>=0)
		{
			Asura_Text_Output::Print(x,y++,0xffffff00,0,"Current Light Sets :");
			x++;

			Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();
			u_int uSets = pxEnv->GetLightSets(iModuleIndex);

			if(uSets)
			{
				for(int i=0;i<TOOLS_MAX_LIGHT_SETS;i++)
				{
					if(uSets & (1<<i))
					{
						const char* szSetName = Tools_LightSets::GetLightSetNameByIndex(i);
						if(szSetName)
						{
							Asura_Text_Output::Print(x,y++,0xff00ff00,0,"%s",szSetName);
						}
					}
				}
			}
			else
			{
				Asura_Text_Output::Print(x,y++,0xff00ff00,0,"None");
			}
		}
	}
}

void Tools_Mode_Module::HandleKeyboard()
{
	if(Asura_Overlay_System::OverlaysHaveKeyboardFocus()) return;
 	if(Asura_UserInput::KeyPressed(ASURA_KEYID_ALT)) return;
 	if(Asura_UserInput::KeyPressed(ASURA_KEYID_CTRL))
 	{
		if(Asura_UserInput::DebouncedKeyPressed('z'))// 'ctrl+z' for  undo
		{
			Undo();
		}
		if(Asura_UserInput::DebouncedKeyPressed('y'))// 'ctrl+y' for  redo
		{
			Redo();
		}
	}
	else if(Asura_UserInput::KeyPressed(ASURA_KEYID_SHIFT))
	{
		if(Asura_UserInput::DebouncedKeyPressed('f'))// 'Shift + F' to remove a flag
		{
			RemoveFlag();
		}
	}
	else
	{
		if(Asura_UserInput::DebouncedKeyPressed('r'))//'R' Rename module
		{
			RenameModule();
		}
		if(Asura_UserInput::DebouncedKeyPressed('f'))// 'F' to apply a flag
		{
			ApplyFlag();
		}
		if(Asura_UserInput::DebouncedKeyPressed(','))// '<' for  undo
		{
			Undo();
		}
		if(Asura_UserInput::DebouncedKeyPressed('.'))// '>' for  redo
		{
			Redo();
		}


	}
}


void Tools_Mode_Module::ToggleModuleOverlay(void)
{
	Asura_Assert(s_pxThis,"");

	s_pxThis->m_bModuleOverlayOpen = !s_pxThis->m_bModuleOverlayOpen;

	if (s_pxThis->m_bModuleOverlayOpen)
	{
		s_pxThis->CreateModuleOverlay();
	}
	else
	{
		Asura_Overlay_System::CloseOverlays(TOOLS_OVERLAY_MODE);
	}
}
bool Tools_Mode_Module::ModuleOverlayIsOn(void)
{
	Asura_Assert(s_pxThis,"");
	return s_pxThis->m_bModuleOverlayOpen;
}

void Tools_Mode_Module::CreateModuleOverlay(void)
{
	if(!m_bModuleOverlayOpen) return;

	Asura_Overlay* pxOverlay;
	pxOverlay = new Asura_Overlay("Module Mode",false,&m_xModuleOverlayPosition);
	
	Asura_Dialog* pxDialog;
	Asura_Vector_2 xOffset = Asura_Vector_2(1.0f,3.0f);
			

	//start of tabs
	static char* s_aszTabs[2] = {"Flags","Light Sets"};
	Asura_Tabs_Dialog* pxTabsDialog = new Asura_Tabs_Dialog(xOffset,s_aszTabs,2);
	pxOverlay->AddDialog(pxTabsDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
	pxOverlay->SetCurrentParentDialog(pxTabsDialog);

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

	//Start of flags tab
	pxTabsDialog->SelectTab(0);

	//heading for flag list
	pxDialog = new Asura_Dialog("Flag :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::SmallSpacing();
	
	//add the flag list
	pxDialog = new Asura_List_Dialog(xOffset,g_aszModuleFlagFlagNames,&m_iCurrentFlagIndex,g_iNumberOfModuleFlags,g_iNumberOfModuleFlags,NULL);
//	pxDialog->SetHelpText("Selected flag.");
	((Asura_List_Dialog*)pxDialog)->SetListHelpStrings(g_aszModuleFlagHelpStrings);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y=pxDialog->m_xMaxCoord.y;
	xOffset.y+=Asura_Dialog::LargeSpacing();

	//end of flags tab
	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//start of light sets tab
	pxTabsDialog->SelectTab(1);
	xOffset.y = fTabsStartY;

	pxDialog = new Asura_Dialog("Light Set :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	for(u_int i=0;i<TOOLS_MAX_LIGHT_SETS;i++)
	{
		const char* szSetName = Tools_LightSets::GetLightSetNameByIndex(i);
		if(!szSetName) continue;

		pxDialog = new Asura_FlagTickbox_Dialog(szSetName, xOffset, &m_uSelectedLightSets, 1<<i);
		pxOverlay->AddDialog(pxDialog);
		xOffset.y+=Asura_Dialog::DefaultSpacing();
	}

	xOffset.y+=Asura_Dialog::LargeSpacing()-Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog("Replace Current", xOffset, &m_bReplaceLightSets);
	pxDialog->SetHelpText("If ticked then 'applying' the light sets will replace the current values on the module with the settings above , instead of just adding the selected ones.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();


	//end of light sets tab
	if(xOffset.y > fTabsEndY) fTabsEndY = xOffset.y;

	//end of tabs
	xOffset.y = fTabsEndY + 1.0f;
	pxOverlay->SetCurrentParentDialog(0);
	pxTabsDialog->SetSelectedTabPointer(&s_uSelectedTab);

	
	pxDialog = new Asura_Function_Dialog("Apply Flag(F)",xOffset,ApplyFlag,(int)this);
	pxDialog->SetHelpText("Add the selected flag to all selected polygons.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Remove Flag (Shift+F)",xOffset,RemoveFlag,(int)this);
	pxDialog->SetHelpText("Remove the selected flag from all selected polygons.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();

	pxDialog = new Asura_Function_Dialog("Undo (Ctrl+Z)",xOffset,Tools_Mode_Module::Undo,(int)this);
	pxDialog->SetHelpText("Undo last change to polygon flags.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxDialog = new Asura_Function_Dialog("Redo (Ctrl+Y)",xOffset,Tools_Mode_Module::Redo,(int)this);
	pxDialog->SetHelpText("Redo change to polygon flags.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	
	pxOverlay->m_uID = TOOLS_OVERLAY_MODE;

	Asura_Overlay_System::SubmitNewOverlay(pxOverlay,false);
}


void Tools_Mode_Module::RenameModule()
{
	int iModule = Tools_Module_Selection::GetHighlitModule();
	if(iModule<0)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"The cursor must be over the module to be renamed.");
		return;
	}

	Asura_Mesh* pxCurrentMesh = Asura_Module_System::GetMeshForModule(iModule);
	Asura_Assert(pxCurrentMesh,"");

	//Base the renaming on the default mesh
	Asura_Mesh* pxDefaultMesh = pxCurrentMesh->GetDefaultPlatformMesh();

	//ask for a new name for the mesh
	GetString_Overlay xOverlay("Rename Module",pxDefaultMesh->Name.GetString());
	if(!xOverlay.DoModal()) return;

	const char* pszNewName = xOverlay.GetString();

	if(!strlen(pszNewName) || !strcmp(pszNewName,pxDefaultMesh->Name.GetString()))
	{
		//name is unchanged or blank , so dont do anything
		return;	
	}

	//make sure this name isn't already used
	if(Asura_Mesh_System::GetMesh(pszNewName))
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"A mesh with that name already exists.");
		return;
	}

	Asura_String xOldName = pxDefaultMesh->Name;

	//update the name in the mesh
	if(Asura_Mesh_System::RenameMesh(pxDefaultMesh,pszNewName))
	{

		//rename platform specific meshes as well
		for(Asura_Mesh* pxPlatMesh = pxDefaultMesh->m_pxNextPlatformMesh; pxPlatMesh; pxPlatMesh = pxPlatMesh->m_pxNextPlatformMesh)
		{
			//get the the old platform name
			char szPlatName[250];
			Asura_PrintfToBfr(szPlatName,"%s",sizeof(szPlatName),true,pxPlatMesh->Name.GetString());

			//Find the bit just past all the platform names
			char* pcPos = strrchr(szPlatName,'#');
			if(pcPos)
				pcPos++;//skip past the '#'
			else
				pcPos = &szPlatName[strlen(szPlatName)];

			//and add on the new mesh name
			int iSpaceLeft = sizeof(szPlatName) - (pcPos - szPlatName);
			Asura_PrintfToBfr(pcPos,"%s",iSpaceLeft,true,pszNewName);

			Asura_Mesh_System::RenameMesh(pxPlatMesh, szPlatName);

		}


		Tools_SaveAsura::SetMeshModified(pxDefaultMesh);
		//(module linking and sound need to be flagged as modified since their files contain the module names)
		Tools_SaveAsura::SetModuleLinkingModified();
		Tools_SaveAsura::SetSoundsModified();

		
		Tools_Timed_Message_System::AddMessage(0xffffff,"%s renamed to %s.",xOldName.GetString(),pszNewName);
	}
}




void Tools_Mode_Module::ApplyFlag()
{
	if(m_eSubMode == SUBMODE_MODULE_FLAGS)
	{
		if(!Tools_Module_Selection::GetNumSelected())
		{
			Tools_Timed_Message_System::AddMessage(0xffffff,"Can't add flag - no modules selected");
			return;
		}

		SetFlag(g_aiModuleFlagValues[m_iCurrentFlagIndex],true);

		Tools_Timed_Message_System::AddMessage(0xffffff,"Added '%s'",g_aszModuleFlagFlagNames[m_iCurrentFlagIndex]);
	}
	else if(m_eSubMode == SUBMODE_LIGHTSETS)
	{
		if(!Tools_Module_Selection::GetNumSelected())
		{
			Tools_Timed_Message_System::AddMessage(0xffffff,"Can't add light sets - no modules selected");
			return;
		}


		if(m_bReplaceLightSets)
		{
			SetLightSets(m_uSelectedLightSets, 0xffffffff);
			Tools_Timed_Message_System::AddMessage(0xffffff,"Replaced light set flags");
		}
		else
		{
			SetLightSets(m_uSelectedLightSets, m_uSelectedLightSets);
			Tools_Timed_Message_System::AddMessage(0xffffff,"Added light set flags");
		}

	}
}

void Tools_Mode_Module::RemoveFlag()
{
	if(m_eSubMode == SUBMODE_MODULE_FLAGS)
	{
		if(!Tools_Module_Selection::GetNumSelected())
		{
			Tools_Timed_Message_System::AddMessage(0xffffff,"Can't remove flag - no modules selected");
			return;
		}

		SetFlag(g_aiModuleFlagValues[m_iCurrentFlagIndex],false);

		Tools_Timed_Message_System::AddMessage(0xffffff,"Removed '%s'",g_aszModuleFlagFlagNames[m_iCurrentFlagIndex]);
	}
	else if(m_eSubMode == SUBMODE_LIGHTSETS)
	{
		if(!Tools_Module_Selection::GetNumSelected())
		{
			Tools_Timed_Message_System::AddMessage(0xffffff,"Can't add light sets - no modules selected");
			return;
		}

		SetLightSets(0, m_uSelectedLightSets);
		Tools_Timed_Message_System::AddMessage(0xffffff,"Removed light set flags");

	}
}

void Tools_Mode_Module::SetFlag( int iFlag, bool bAdd )
{
	//log for undo
	PrepareUndo();


	const List<int>* pxModuleList = Tools_Module_Selection::GetSelectionList();

	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();
	for(CLIF<int> xModuleLIF(pxModuleList);!xModuleLIF.done();xModuleLIF.next())
	{
		if(bAdd)
			pxEnv->AddModuleFlag(xModuleLIF(),(ASURA_MODULE_FLAG)iFlag);
		else
			pxEnv->RemoveModuleFlag(xModuleLIF(),(ASURA_MODULE_FLAG)iFlag);
	
	}
}


void Tools_Mode_Module::SetLightSets( u_int uLightSets, u_int uMask )
{
	//log for undo
	PrepareUndo();


	const List<int>* pxModuleList = Tools_Module_Selection::GetSelectionList();

	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();
	for(CLIF<int> xModuleLIF(pxModuleList);!xModuleLIF.done();xModuleLIF.next())
	{
		u_int uNewLightSets = pxEnv->GetLightSets(xModuleLIF());

		uNewLightSets &=~ uMask;
		uNewLightSets |= (uLightSets & uMask);
		
		pxEnv->SetLightSets(xModuleLIF(), uNewLightSets);
	}
}


void Tools_Mode_Module::Undo()
{
	if(m_xModuleUndo.Undo())
	{
		Tools_Timed_Message_System::AddMessage(0xffffff,"Undo");
	}
}
void Tools_Mode_Module::Redo()
{
	if(m_xModuleUndo.Redo())
	{
		Tools_Timed_Message_System::AddMessage(0xffffff,"Redo");
	}
}


void Tools_Mode_Module::PrepareUndo()
{
	const List<int>* pxModuleList = Tools_Module_Selection::GetSelectionList();
	if(!pxModuleList->size()) return;

	for(CLIF<int> xModuleLIF(pxModuleList);!xModuleLIF.done();xModuleLIF.next())
	{
		if(m_eSubMode == SUBMODE_MODULE_FLAGS)
			m_xModuleUndo.LogFlagsChanged(xModuleLIF());
		else
			m_xModuleUndo.LogLightSetsChanged(xModuleLIF());

		Tools_SaveAsura::SetModuleModified(xModuleLIF());

	}

}

void Tools_Mode_Module::UpdateSubModeFromSelectedTab()
{
	//Tabs directly correspond to the submodes for now
	if(s_uSelectedTab == 0)
	{
		m_eSubMode = SUBMODE_MODULE_FLAGS;		
	}
	else if(s_uSelectedTab == 1)
	{
		m_eSubMode = SUBMODE_LIGHTSETS;		
	}
	else
	{
		Asura_Assert(0, "Submode not defined for the selected tab");
	}
}


/////////////////////////////////////////////////////////////////////////////////////////
/*---------------**
** ModuleModeUndo **
**---------------*/


void ModuleModeUndo::ProcessUndoData(void* pData)
{
	ModuleUndoData* pxUndoData = (ModuleUndoData*) pData;
	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();

	
	switch(pxUndoData->m_eUndoType)
	{
		case ModuleUndoData::UndoType_FlagsChanged :
		{
			
			//store current flags and update from undo data
			u_int uFlags = pxEnv->GetModuleFlags(pxUndoData->m_iModuleIndex);
			pxEnv->SetModuleFlags(pxUndoData->m_iModuleIndex,pxUndoData->m_uFlags);

			//convert the undo data
			pxUndoData->m_uFlags = uFlags;

			Tools_SaveAsura::SetModuleModified(pxUndoData->m_iModuleIndex);

			break;
		}

		case ModuleUndoData::UndoType_LightSetsChanged :
		{
			
			//store current light sets and update from undo data
			u_int uFlags = pxEnv->GetLightSets(pxUndoData->m_iModuleIndex);
			pxEnv->SetLightSets(pxUndoData->m_iModuleIndex,pxUndoData->m_uFlags);

			//convert the undo data
			pxUndoData->m_uFlags = uFlags;

			Tools_SaveAsura::SetModuleModified(pxUndoData->m_iModuleIndex);

			break;
		}


		default :
			Asura_Assert(0,"Unexpected undo type for module flag editing");
			break;
	}
}

void ModuleModeUndo::LogFlagsChanged(int iModuleIndex)
{
	//allocate undo data
	ModuleUndoData* pxUndo = (ModuleUndoData*) AllocateNextUndoData();
	if(!pxUndo) return;

	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();

	
	//fill in the undo data	
	pxUndo->m_eUndoType = ModuleUndoData::UndoType_FlagsChanged;
	pxUndo->m_iModuleIndex = iModuleIndex;
	pxUndo->m_uFlags = pxEnv->GetModuleFlags(iModuleIndex);
}

void ModuleModeUndo::LogLightSetsChanged(int iModuleIndex)
{
	//allocate undo data
	ModuleUndoData* pxUndo = (ModuleUndoData*) AllocateNextUndoData();
	if(!pxUndo) return;

	Asura_Environment* pxEnv = Asura_Environment_System::GetEnvironment();

	
	//fill in the undo data	
	pxUndo->m_eUndoType = ModuleUndoData::UndoType_LightSetsChanged;
	pxUndo->m_iModuleIndex = iModuleIndex;
	pxUndo->m_uFlags = pxEnv->GetLightSets(iModuleIndex);
}
