//===========================================================================//
// File:	MWMission.cpp                                                    //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//																		     //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "MW4Headers.hpp"

#include "MWMission.hpp"
#include "rail_move.hpp"

#include <Adept\Map.hpp>
#include <Adept\Tool.hpp>
#include "gameinfo.hpp"

using namespace MW4AI;
using namespace MechWarrior4;
using namespace Adept;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWMission__CreateMessage::ConstructCreateMessage(Script *script)
{
	Check_Object(script);
	#if defined(_ARMOR)
		int stack_level = Tool::Instance->GetStackLevel();
	#endif

#ifdef LAB_ONLY
	strcpy(MWGameInfo::g_ResourceFile, (char *)(script->instancePage->GetNotationFile()->GetFileName()));
	strcpy(MWGameInfo::g_ResourceEntry, (char *)(script->instancePage->GetName()));
#endif
	//
	//--------------
	// Set up stream
	//--------------
	//
  UserConstants::IncrementRefCount ();
	MemoryStream *message_stream = script->messageStream;
	Check_Object(message_stream);
	message_stream->AllocateBytes(sizeof(MWMission__CreateMessage));
	Mission__CreateMessage::ConstructCreateMessage(script);
	MWMission__CreateMessage *message =
		Cast_Pointer(
			MWMission__CreateMessage*,
			message_stream->GetPointer()
		);
	message->messageLength = sizeof(*message);
//#JPS check not valid since entries can be mapped	Verify(message->m_mapResourceID == ResourceID(MapResourceFileID,1));

	//
	//---------------------------------------------------------------
	// Point at the notation file and make other files relative to it
	//---------------------------------------------------------------
	//
	Page *page = script->instancePage;
	Check_Object(page);
	NotationFile *instance_file = page->GetNotationFile();
	Check_Object(instance_file);
	Check_Object(Tool::Instance);
	Tool::Instance->PushFilePath(instance_file);

	Scalar discheck;
	discheck = 1200.0f;
	page->GetEntry ("Distance Check",&discheck);
	message->distanceCheck = discheck;

	//
	//-----------------------------------------------
	// Find the name of the script to load for this mission
	//-----------------------------------------------
	//
	const char *ablscript;

	message->scriptName[0] = 0;
	if (page->GetEntry ("Script",&ablscript))
	{
/*
		if (strnicmp (ablscript,"Content",7))
		{
			Str_Copy (message->scriptName,"Content\\",sizeof (message->scriptName));		// hack because directories change when running the game.
			if (stricmp (Tool::Instance->GetCurrentStackPath (),"Games\\"))
				Str_Cat (message->scriptName,Tool::Instance->GetCurrentStackPath (),sizeof (message->scriptName));
			Str_Cat (message->scriptName,ablscript,sizeof (message->scriptName));
		}
		else
*/
		{
			if (gos_DoesFileExist (ablscript))
			{
				if (FileStream::IsRedirected)
				{
					Str_Copy (message->scriptName,FileStream::RedirectedName,sizeof (message->scriptName));
				}
				else
				{
					Str_Copy (message->scriptName,ablscript,sizeof (message->scriptName));
				}
				FileStream::IsRedirected = false;
			}
			else
				message->scriptName[0] = 0;
		}
	}

	//
	//---------------------
	//Set up the Rail Graph
	//---------------------
	//
	message->railgraphStreamResourceID = ResourceID::Null;
	NotationFile graph_file;
	if (page->GetEntry("RailGraph", &graph_file))
	{
		const char *graph_filename = graph_file.GetFileName();
		Check_Pointer(graph_filename);
		Check_Object(Tool::Instance);

		//
		//---------------------------------------------------------------
		// Look for the graph stream resource to see if it is up to date
		//---------------------------------------------------------------
		//
		Resource graph_resource(graph_filename);
		if (graph_resource.DoesResourceExist() && graph_resource.IsResourceUpToDate())
		{
			message->railgraphStreamResourceID = graph_resource.GetResourceID();
			Check_Object(Resource::ParentFileDependencies);
			if (!graph_resource.IsRegistered())
				graph_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
		}
		else
		{

			//
			//---------------------------------------
			// For each page, an entity will be built
			//---------------------------------------
			//
			FileDependencies graph_deps(*graph_file.GetFileDependencies());
			FileDependencies *parent = Resource::ParentFileDependencies;
			Resource::ParentFileDependencies = &graph_deps;
			Tool::Instance->PushFilePath(&graph_file);
			DynamicMemoryStream graph_stream;

			//
			//---------------------------------------
			// Create the damage Object for this page
			//---------------------------------------
			//
			CRailGraph::ConstructGraphObjectStream(&graph_stream,&graph_file);

			//
			//-----------------------------------------
			// Only save out the stream if there is one
			//-----------------------------------------
			//
			if (graph_stream.GetBytesUsed())
			{
				graph_resource.Save(&graph_stream, &graph_deps);
				if (!graph_resource.IsRegistered())
					parent->AddDependencies(&graph_deps);
				Check_Object(&graph_resource);
				message->railgraphStreamResourceID = graph_resource.GetResourceID();
			}
			else
				message->railgraphStreamResourceID = ResourceID::Null;
			Resource::ParentFileDependencies = parent;
		
			//------------------------
			// Clean up the tool stack
			//------------------------
			//
			Tool::Instance->PopFilePath();
		}
	}
	Tool::Instance->PopFilePath();
	Verify(stack_level == Tool::Instance->GetStackLevel());
  UserConstants::DecrementRefCount ();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWMission::SaveInstanceText(Stuff::Page *page)
{
	Mission::SaveInstanceText(page);
	
	Resource graph_res(railgraphStreamResourceID);
	page->SetEntry("RailGraph",graph_res.GetName());
	if(strcmp(scriptName,""))
		page->SetEntry("Script",scriptName);

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWMission__GameModel::ConstructGameModel(Script *script)
{
	Check_Object(script);
	Check_Object(Tool::Instance);
	#if defined(_ARMOR)
		int stack_index = Tool::Instance->GetStackLevel();
	#endif

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *model_stream = script->modelStream;
	Check_Object(model_stream);
	model_stream->AllocateBytes(sizeof(MWMission__GameModel));
	Mission__GameModel::ConstructGameModel(script);
	MWMission__GameModel *model =
		Cast_Pointer(MWMission__GameModel*, model_stream->GetPointer());
	Check_Object(model);
	NotationFile *model_file = script->modelFile;
	Check_Object(model_file);
	Tool::Instance->PushFilePath(model_file);
	Page *page = model_file->GetPage("GameData");
	Check_Object(page);
	//
	//---------------------------------------------
	//Create the array of Damage Effect ResourceIDs
	//---------------------------------------------
	//
	model->m_animatedTexturesResourceID = ResourceID::Null;
	{
		NotationFile texture_file;
		if (!page->GetEntry("TextureAnimations", &texture_file))
			model->m_animatedTexturesResourceID = ResourceID::Null;
		else
		{
			const char *texture_file_name = texture_file.GetFileName();
			Check_Pointer(texture_file_name);

			//
			//------------------------------------------------------------------
			// Look for the subsystem stream resource to see if it is up to date
			//------------------------------------------------------------------
			//
			Resource texture_resource(texture_file_name);
			if (
				texture_resource.DoesResourceExist() &&
				texture_resource.IsResourceUpToDate()
			)
			{
				model->m_animatedTexturesResourceID = texture_resource.GetResourceID();
				if (!texture_resource.IsRegistered())
					texture_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
			}

			//
			//---------------------------------------------------------------
			// Its not up to date, so we will have to build the texture stuff
			//---------------------------------------------------------------
			//
			else
			{
				Tool::Instance->PushFilePath(&texture_file);
				NotationFile::PageIterator *textures = texture_file.MakePageIterator();
				Check_Object(textures);
				DynamicMemoryStream texture_stream;
				Page *texture;
				texture_stream << textures->GetSize();
				while ((texture = textures->ReadAndNext()) != NULL)
				{
					Check_Object(texture);

					//
					//--------------------------------
					// Create the entity for this page
					//--------------------------------
					//
					const char *texture_data_name;
					texture->GetEntry("TextureName", &texture_data_name, true);
					Check_Pointer(texture_data_name);
					texture_stream << MString(texture_data_name);
					const char *texture_anim_name;
					texture->GetEntry("AnimationName", &texture_anim_name, true);
					Check_Pointer(texture_anim_name);
					texture_stream << MString(texture_anim_name);
					Scalar anim_speed = 1.0f;
					texture->GetEntry("AnimationSpeed", &anim_speed);
					texture_stream << anim_speed;
				}
				//
				//-----------------------------------------
				// Only save out the stream if there is one
				//-----------------------------------------
				//
				if (texture_stream.GetBytesUsed() > sizeof(int))
				{
					texture_resource.Save(
						&texture_stream,
						texture_file.GetFileDependencies()
					);
					Check_Object(&texture_resource);
					if (!texture_resource.IsRegistered())
						texture_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
					model->m_animatedTexturesResourceID = texture_resource.GetResourceID();
				}
				else
					model->m_animatedTexturesResourceID = ResourceID::Null;
				
				//
				//------------------------
				// Clean up the tool stack
				//------------------------
				//
				Check_Object(textures);
				delete textures;
				Tool::Instance->PopFilePath();
			}
		}
	}

	//
	//---------------------------------------------
	//Create the array of Texture Movie ResourceIDs
	//---------------------------------------------
	//
	model->m_movieTexturesResourceID = ResourceID::Null;
	{
		NotationFile texture_file;
		if (!page->GetEntry("TextureMovies", &texture_file))
			model->m_movieTexturesResourceID = ResourceID::Null;
		else
		{
			const char *texture_file_name = texture_file.GetFileName();
			Check_Pointer(texture_file_name);

			//
			//------------------------------------------------------------------
			// Look for the subsystem stream resource to see if it is up to date
			//------------------------------------------------------------------
			//
			Resource texture_resource(texture_file_name);
			if (
				texture_resource.DoesResourceExist() &&
				texture_resource.IsResourceUpToDate()
			)
			{
				model->m_movieTexturesResourceID = texture_resource.GetResourceID();
				if (!texture_resource.IsRegistered())
					texture_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
			}

			//
			//---------------------------------------------------------------
			// Its not up to date, so we will have to build the texture stuff
			//---------------------------------------------------------------
			//
			else
			{
				Tool::Instance->PushFilePath(&texture_file);
				NotationFile::PageIterator *textures = texture_file.MakePageIterator();
				Check_Object(textures);
				DynamicMemoryStream texture_stream;
				Page *texture;
				texture_stream << textures->GetSize();
				while ((texture = textures->ReadAndNext()) != NULL)
				{
					Check_Object(texture);

					//
					//--------------------------------
					// Create the entity for this page
					//--------------------------------
					//
					const char *texture_data_name;
					texture->GetEntry("TextureName", &texture_data_name, true);
					Check_Pointer(texture_data_name);
					texture_stream << MString(texture_data_name);
//					const char *texture_anim_name;
//					texture->GetEntry("AnimationName", &texture_anim_name, true);
//					Check_Pointer(texture_anim_name);
//					texture_stream << MString(texture_anim_name);
					Scalar frame_time = 0.01f;
					texture->GetEntry("FrameTime", &frame_time);
					texture_stream << frame_time;
				}
				//
				//-----------------------------------------
				// Only save out the stream if there is one
				//-----------------------------------------
				//
				if (texture_stream.GetBytesUsed() > sizeof(int))
				{
					texture_resource.Save(
						&texture_stream,
						texture_file.GetFileDependencies()
					);
					Check_Object(&texture_resource);
					if (!texture_resource.IsRegistered())
						texture_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
					model->m_movieTexturesResourceID = texture_resource.GetResourceID();
				}
				else
					model->m_movieTexturesResourceID = ResourceID::Null;
				
				//
				//------------------------
				// Clean up the tool stack
				//------------------------
				//
				Check_Object(textures);
				delete textures;
				Tool::Instance->PopFilePath();
			}
		}
	}
	Tool::Instance->PopFilePath();
	Verify(stack_index == Tool::Instance->GetStackLevel());
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MWMission__GameModel::SaveGameModel(
		MWMission__GameModel *model,
		Stuff::NotationFile *data_file
	)
{
	Check_Object(model);
	Check_Object(data_file);

	Mission__GameModel::SaveGameModel(model, data_file);
	Page *page = data_file->GetPage("GameData");
	//Save animated Textures file name
	if(model->m_animatedTexturesResourceID != ResourceID::Null)
	{
		Resource anim_textures(model->m_animatedTexturesResourceID);
		Verify(anim_textures.DoesResourceExist());
		
		page->SetEntry("TextureAnimations", anim_textures.GetName());
	}

	page->SetEntry("Cull", "NeverCull");
}