// EditorApplication.cpp: implementation of the EditorApplication class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MW4GameEd2.h"
#include "EditorApplication.h"
#include <MW4\MWTool.hpp>
#include <MW4\MWPlayer.hpp>
#include <Buildnum\BuildNum.h>
#include <Adept\Resource.hpp>
#include <Adept\DropZone.hpp>
#include <Adept\Map.hpp>
#include <Adept\ResourceEffectLibrary.hpp>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//#############################################################################
//########################     EditorApplication      ######################
//#############################################################################

//#############################################################################
// Message Support
//
const Receiver::MessageEntry
	EditorApplication::MessageEntries[]=
{
	MESSAGE_ENTRY(EditorApplication, PauseGame)
};

EditorApplication::ClassData*
	EditorApplication::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorApplication::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			EditorApplicationClassID,
			"EditorApplication",
			MWApplication::DefaultData,
			ELEMENTS(MessageEntries),
			MessageEntries
		);
	Check_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorApplication::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorApplication*
	EditorApplication::Make()
{
	return new EditorApplication;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorApplication::EditorApplication():
	MWApplication(DefaultData,false)
{
	applicationMode = EditorMode;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EditorApplication::~EditorApplication()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorApplication::LoadGameMessageHandler(int connection, Stuff::MemoryStream *message)
{
	Check_Object(this);
	MWApplication::LoadGameMessageHandler(connection, message);

	
	//
	//-------------------------------------------------------
	//We need to create a drop zone with the name PlayerStart
	//-------------------------------------------------------
	//
	if(NameTable::GetInstance()->FindID("PlayerStart") == NameTable::NullObjectID)
	{
		Adept::Resource model_resource((LPCSTR)"Content\\Misc\\DropZone\\DropZone.instance");
		Check_Object(&model_resource);
		model_resource.LoadData();
		Verify(model_resource.DoesResourceExist());
	
		Adept::Entity *entity;
		Check_Object(Connection::Local);
		ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
		entity = Entity::CreateEntity(&model_resource,&base_id);
		Check_Object(entity);

		entity->instanceName = "PlayerStart";
		Check_Object(Map::GetInstance());
		Map::GetInstance()->AddChild(entity);

		entity->SetPropType(Entity::MissionPropType);
		entity->SyncMatrices(true);

		NameTable::GetInstance()->AddEntry(entity, NameTable::DropZoneArray);
		Verify(NameTable::GetInstance()->IsValid());
		Map::GetInstance()->UpdateZone(entity);
	}

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	EditorApplication::EnterRunningGameState(void* data)
{
	Check_Object(this);
	MWApplication::EnterRunningGameState(data);
}

void
	EditorApplication::PauseGameMessageHandler(const PauseGameMessage *message)
{
	Check_Object(this);
	Check_Object(message);
	Verify(message->messageID == PauseGameMessageID);
}


void
	EditorApplication::LoadMissionResources(const char *mission_name)
{

	//
	//---------------------------------------------------------
	// Get the mission instance name and the resource file name
	//---------------------------------------------------------
	//
	Stuff::MString mission_instance = mission_name;

	// [editor data fix] Derive the mission's compiled resource (.mw4) so BOTH user missions
	// (Resource\UserMissions\<name>.mw4) AND stock missions can be opened. Stock missions
	// compile to Resource\Missions\<short>.mw4 where <short> is an abbreviated, lowercase name
	// declared in the mission's .build (e.g. CentralPark -> cpark.mw4), so it can't be derived
	// by a simple transform. The original code hardcoded "Resource\\User" + (name after first
	// '\\'), which only ever found the few user missions and produced a garbage path (and STOP)
	// for any name lacking a '\\'. Now: extract the bare mission name, prefer the user-mission
	// package, else read the resource path straight out of <name>.build.
	char _bare[256];
	{
		const char* _s = strrchr( (const char*)mission_instance, '\\' );
		_s = _s ? _s + 1 : (const char*)mission_instance;
		Str_Copy( _bare, _s, sizeof(_bare) );
		char* _dot = strrchr( _bare, '.' );
		if( _dot ) *_dot = 0;
	}
	Stuff::MString res_name = "Resource\\UserMissions\\";
	res_name += _bare;
	res_name += ".mw4";
	if( GetFileAttributes( (const char*)res_name ) == 0xFFFFFFFF )	// no user-mission package -> stock mission
	{
		char _bp[512];
		sprintf( _bp, "Content\\Missions\\%s\\%s.build", _bare, _bare );
		FILE* _bf = fopen( _bp, "r" );
		if( _bf )
		{
			char _ln[512];
			while( fgets( _ln, sizeof(_ln), _bf ) )
			{
				char* _lb = strchr( _ln, '[' );
				char* _rb = _lb ? strchr( _lb, ']' ) : 0;
				if( _lb && _rb && _rb > _lb && strstr( _lb, ".mw4" ) )
				{
					*_rb = 0;
					res_name = _lb + 1;		// e.g. resource\missions\cpark.mw4
					break;
				}
			}
			fclose( _bf );
		}
	}

	//
	// Since databases override the file hooking I have to specifically 
	// make sure we do or don't need to translate the name at this point.
	//
	TranslateMissionNameIfNecessary(res_name);
	//
	//-------------------------------------------------------------------
	// Open up the resource file as a database and access record 0.  This
	// will contain the list of resource files this one is dependant on
	//-------------------------------------------------------------------
	//

	Stuff::DatabaseHandle *database =
		new Stuff::DatabaseHandle(res_name, false, VER_CONTENTVERSION);
	Stuff::RecordHandle record;
	record.m_databaseHandle = database;
	record.m_ID = ResourceID::BuildDependenciesRecordID;
	#if defined(_ARMOR)
		bool result =
	#endif
	record.FindID(true);
	Verify(result);

	//
	//-------------------------
	// Load up the core effects
	//-------------------------
	//
	Verify(!gosFX::EffectLibrary::Instance);
	gosFX::EffectLibrary::Instance = new ResourceEffectLibrary;
	Resource core_libraries("{effects}");
	Verify(core_libraries.DoesResourceExist());
	core_libraries.LoadData();
	ResourceID *lib = Cast_Pointer(ResourceID*, core_libraries.GetPointer());
	for (unsigned i=0; i<core_libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
	{
		Resource library(*lib);
		gosFX::EffectLibrary::Instance->Load(&library);
	}

	//
	//----------------------------------------------------------------------
	// The data points to a series of null terminated strings.  Step through
	// them until done
	//----------------------------------------------------------------------
	//
	const char* data = reinterpret_cast<const char*>(record.m_data);
	short level=MapResourceFileID;
	for (DWORD count=0; count<record.m_length; ++level)
	{
		if (!data[count])
			break;

//		MString depstr=data+count;
//		strcpy(strrchr(depstr,'.')+1,"dep");
		//
		//---------------------------
		// Load this resource file up
		//---------------------------
		//
		ResourceManager::Instance->OpenResourceFile(
			data+count,
			NULL,
			level,
			VER_CONTENTVERSION,
			false,
			false
		);

		//
		//----------------------------
		// Load up this file's effects
		//----------------------------
		//
		Resource libraries("{effects}");
		libraries.LoadData();
		if (libraries.DoesResourceExist() && libraries.GetResourceID().GetFileID() == level)
		{
			ResourceID *lib = Cast_Pointer(ResourceID*, libraries.GetPointer());
			for (unsigned i=0; i<libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
			{
				Resource library(*lib);
				gosFX::EffectLibrary::Instance->Load(&library);
			}
		}
		count += strlen(data+count)+1;
	}
//
	//---------------------------------
	// Now create our own resource file
	//---------------------------------
	//
//	MString depstr=res_name;
//	strcpy(strrchr(depstr,'.')+1,"dep");

	ResourceManager::Instance->OpenResourceFile(database, 
												level,
												false);
	Resource libraries("{effects}");
	libraries.LoadData();
	if (libraries.DoesResourceExist() && libraries.GetResourceID().GetFileID() == level)
	{
		ResourceID *lib = Cast_Pointer(ResourceID*, libraries.GetPointer());
		for (unsigned i=0; i<libraries.GetSize()/sizeof(ResourceID); ++i, ++lib)
		{
			Resource library(*lib);
			gosFX::EffectLibrary::Instance->Load(&library);
		}
	}
}


Entity::CreateMessage *
	EditorApplication::MakePlayerCreationMessage(int player_id)
{
	
	Resource vehicle_instance("Content\\Vehicles\\ObservationVehicle\\ObservationVehicle.instance");	
	vehicle_instance.LoadData();
	MString interface_name = "Interfaces\\SimpleInterface\\SimpleInterface.instance";
	Resource interface_instance(interface_name);
	interface_instance.LoadData();
	Resource player_data("Players\\TestPlayer\\TestPlayer.data");
	player_data.LoadData();
	
	MWPlayer::CreateMessage *player_message =
		new MWPlayer::CreateMessage(
		sizeof(MWPlayer::CreateMessage),
		DefaultEventPriority,
		MWPlayer::CreateMessage::DefaultFlags,
		MWPlayerClassID,
		0,
		player_data.GetResourceID(),
		LinearMatrix4D::Identity,
		0.0f,
		MWPlayer::ExecutionStateEngine::AlwaysExecuteState,
		NameTableEntry::BuildObjectID(NameTable::PlayerArray, 0),
		Entity::Player,
		vehicle_instance.GetResourceID(),
		interface_instance.GetResourceID(),
		NameTable::NullObjectID,
		0,
		DefaultSkinPrefix,
		0,
		0
		);
	Check_Object(player_message);

	return player_message;

}

