//
// Tools_PlatformMesh_System.cp
//
// Created by Richard Rice - 13/03/2007
// 
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Mesh/Tools_PlatformMesh_System.h"

//asura
#if defined( ASURA_USE_CARPET)
	#include "Carpet/Asura_Direct3D_Carpet_Game_Render.h"
#endif
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Mesh/Asura_Mesh.h"
#include "Rendering/Asura_Module.h"

//tools
#include "Tools_System.h"
#include "Tools_Mode.h"
#include "Hierarchy/Tools_Animation_Files.h"
#include "Lighting/Tools_GlobalIllumination_EntitySamples.h"
#include "Load&Save/LevelExport/Tools_Level_Export.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Adjacency.h"
#include "Misc/Tools_Platform.h"
#include "Misc/Tools_Polygon_Selection.h"
#include "Misc/Tools_Vertex_Selection.h"
#include "Misc/Tools_VertexPerPoly_Selection.h"
#include "Misc/Tools_Edge_Selection.h"
#include "Misc/Tools_Render_Options.h"
#include "Rendering/Tools_RenderModules.h"
#include "Sound/Tools_SoundEvent_System.h"
#include "Streaming/Tools_Streaming_System.h"
#if defined ASURA_USE_MATERIAL_RESPONSE_SYSTEM
#include "Texturing/Tools_Texturing_MaterialResponse.h"
#endif


int Tools_PlatformMesh_System::s_iPlatform = iTOOLS_PLATFORMMESH_DEFAULT;
int Tools_PlatformMesh_System::s_iSelectedPlatform = iTOOLS_PLATFORMMESH_DEFAULT;
int Tools_PlatformMesh_System::s_iDropListIndex = 0;
bool Tools_PlatformMesh_System::s_bNeedToReloadSkinsAndAnims = false;
bool Tools_PlatformMesh_System::s_bNeedToReloadSounds = false;
bool Tools_PlatformMesh_System::s_bReloadFilesWhenChangingPlatform = false;

static int g_iNumPlatformNames = 0;
static const char* g_aszPlatformNames[TOOLS_PLATFORM_NUM_PLATFORMS+1];
static int g_aiPlatforms[TOOLS_PLATFORM_NUM_PLATFORMS+1];

static const int g_iPlatformStackSize = 16;
static int g_aiPlatformStack[g_iPlatformStackSize];
static int g_iNumPlatformStackEntries = 0;


void Tools_PlatformMesh_System::SetPlatform(int iPlatform,bool bTemp)
{

	Asura_Assert(iPlatform >= iTOOLS_PLATFORMMESH_DEFAULT && iPlatform < TOOLS_PLATFORM_NUM_PLATFORMS,"Unexpected platfrom index");
	if(iPlatform == s_iPlatform) return;

	s_iPlatform = iPlatform;
	u_int uPlatformBit = (s_iPlatform == iTOOLS_PLATFORMMESH_DEFAULT) ? 0 : (1<<s_iPlatform);

	bool bAnyChange = false;

	//Update the current mesh used by the modules in each zone
	for(Tools_Streaming_Iterator xIt;!xIt.Done();xIt.Next())
	{
		for(int i=0;i<Asura_Module_System::GetNumberOfModules();i++)
		{
			if(Asura_Module_System::SwitchPlatformMesh(i,uPlatformBit))
			{

				Asura_Mesh* pxMesh = Asura_Module_System::GetMeshForModule(i);
				Tools_RenderModule_System::UpdateModuleMesh(pxMesh->Index);
				Tools_Adjacency::InvalidateModule(i);

				if(xIt.IsMainZone())
				{
					if(!bTemp)
					{
						Tools_Polygon_Selection::HandleMeshChange(i);
						Tools_Vertex_Selection::HandleMeshChange(i);
						Tools_VertexPerPoly_Selection::HandleMeshChange(i);
						Tools_Edge_Selection::HandleMeshChange(i);
						Tools_Render_Options::HandleMeshChange(i);

						if(Tools_System::GetCurrentModeClass())
						{
							Tools_System::GetCurrentModeClass()->HandleMeshChange(i);
						}
					}

					bAnyChange = true;
				}
			}
		}
	}

	if(bAnyChange)
	{
		if(!bTemp)
		{
			Tools_Undo_System::ClearUndo();
		}
		Tools_GlobalIllumination_EntitySamples::Reset();

		//the carpet data refers to polygon/vertex indeces for lighting.
		#if defined( ASURA_USE_CARPET)
		Asura_Direct3D_Carpet_Game_Render::ClearDataSet();
		#endif

	}

	s_bNeedToReloadSkinsAndAnims = true;
	s_bNeedToReloadSounds = true;

}

void Tools_PlatformMesh_System::PushPlatform(int iPlatform,bool bTemp)
{
	//add current platform to stack of changes
	if(g_iNumPlatformStackEntries == g_iPlatformStackSize)
	{
		Asura_Assert(0,"Too many platform changes on stack");
		g_iNumPlatformStackEntries--;
	}
	g_aiPlatformStack[g_iNumPlatformStackEntries++] = s_iPlatform;

	//and change platform
	SetPlatform(iPlatform,bTemp);
}

void Tools_PlatformMesh_System::PopPlatform(bool bTemp)
{
	Asura_Assert(g_iNumPlatformStackEntries,"No entries left on platform change stack");

	//revert to previous platform
	if(g_iNumPlatformStackEntries)
	{
		SetPlatform(g_aiPlatformStack[--g_iNumPlatformStackEntries],bTemp);
	}
}


void Tools_PlatformMesh_System::AddOverlayControls(Asura_Overlay* pxOverlay, Asura_Vector_2& xOffset, bool bAddUpdateSkinsDialog/*=true*/)
{
	//Initialise list of platform names , if not done yet
	if(!g_iNumPlatformNames)
	{
		//add default platform
		g_aszPlatformNames[0] = "Default/PC";
		g_aiPlatforms[0] = -1;
		g_iNumPlatformNames = 1;

		//add other platforms supported by the project
		for(int i=0;i<TOOLS_PLATFORM_NUM_PLATFORMS;i++)
		{
			if(Tools_Level_Export::IsPlatformSupported((Tools_Level_Export::EXPORT_TYPE)i))
			{
				g_aszPlatformNames[g_iNumPlatformNames] = Tools_Platform::GetPlatformName(i);
				g_aiPlatforms[g_iNumPlatformNames] = i;
				g_iNumPlatformNames++;
			}
		}
	}

	Asura_Dialog* pxDialog;
//	pxDialog = new Asura_Dialog("Platform :",xOffset);
//	pxOverlay->AddDialog(pxDialog);
//	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_DropDown_List_Dialog(xOffset,g_aszPlatformNames,&s_iDropListIndex,10,g_iNumPlatformNames,SelectedPlatformChanged, NULL, "Platform");
	pxDialog->SetHelpText("Select which platform to view meshes and phonons for.\nDefault is either treated as the non platform-specific version or PC, depending on the system asking.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	if( bAddUpdateSkinsDialog )
	{	
		#ifdef ASURA_SUPPORT_PLATFORM_HASHED_FILENAMES
		//add option for automatically updating skins/anims
		pxDialog = new Asura_Tickbox_Dialog("Update Skins/Anims",xOffset,&s_bReloadFilesWhenChangingPlatform);
		pxDialog->SetHelpText("If this is ticked , then any platform specific skins and animations will be reloaded when changing the platform being viewed.\n");
		pxOverlay->AddDialog(pxDialog);
		xOffset.y += Asura_Dialog::DefaultSpacing();
		#endif
	}	

	
	
}

void Tools_PlatformMesh_System::SelectedPlatformChanged()
{
	 s_iSelectedPlatform = g_aiPlatforms[s_iDropListIndex];

	 //Any platform changes by code for exports etc should have been finished by the time the user can 
	 //change anything.
	 Asura_Assert(g_iNumPlatformStackEntries==0,"Not expecting any code-based platform changes to be stacked up");
	 g_iNumPlatformStackEntries = 0;

	 if( s_iSelectedPlatform != s_iPlatform )
	 {
		 SetPlatform(s_iSelectedPlatform, false);
		 if( s_bReloadFilesWhenChangingPlatform )
		 {
			 ReloadSkinsAndAnims();
		 }
		 ReloadSounds();
	 }
}

void Tools_PlatformMesh_System::ReloadFilesIfNeeded()
{
	if(s_bNeedToReloadSkinsAndAnims)
	{
		ReloadSkinsAndAnims();
	}
	if(s_bNeedToReloadSounds)
	{
		ReloadSounds();
	}
}

void Tools_PlatformMesh_System::ReloadSkinsAndAnims()
{
	#ifdef ASURA_SUPPORT_PLATFORM_HASHED_FILENAMES
	//check for modified asura files (which are just skin/anim files at the mometn)
	if(Tools_SaveAsura::AreAsuraFilesModified())
	{
		//ask whether to save
		if(ShowYesNoOverlay("%d skins//anims are marked as modified.\nIf these aren't saved now ,the changes will be lost because of loading files for a different platform.\nWould you like to save?",Tools_SaveAsura::GetNumModifiedAsuraFiles()))
		{
			Tools_SaveAsura::SaveModifiedAsuraFiles();			
		}
		Tools_SaveAsura::ClearModifiedAsuraFileList();
	}

	//Make sure the hashed filename system is up to date.
	//Can't rely on saved data , because there is no convenient way to test for platform specific files being added
	Asura_HashedFilename_System::RebuildTreeIfUsingSavedData();

	//reload any platform specific skins/anims
	Tools_Animation_Files::ReloadAnimations(TOOLS_ANIMATION_RELOAD_PLATFORMSPECIFIC);
	Tools_Animation_Files::ReloadSkins(TOOLS_ANIMATION_RELOAD_PLATFORMSPECIFIC);
	#endif


	s_bNeedToReloadSkinsAndAnims = false;
}

void Tools_PlatformMesh_System::ReloadSounds()
{
	Tools_SoundEvent_System::LoadSoundEventsForPlatform(s_iPlatform);

	s_bNeedToReloadSounds = false;
}

int Tools_PlatformMesh_System::GetPlatform(bool bAllowDefault /*=false*/)
{
	if(s_iPlatform == iTOOLS_PLATFORMMESH_DEFAULT && !bAllowDefault)
	{
		return TOOLS_PLATFORM_PC;
	}
	return s_iPlatform;
}
