//===========================================================================//
// File:	MWMover_Tool.cpp									
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 09/09/98  JSE  Inital base class based off of Shadowrun/Adept
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "MW4Headers.hpp"

#include "MWMover.hpp"
#include "MWTool.hpp"
#include <Adept\EntityManager.hpp>

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

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *message_stream = script->messageStream;
	Check_Object(message_stream);
	message_stream->AllocateBytes(sizeof(MWMover__CreateMessage));
	Mover__CreateMessage::ConstructCreateMessage(script);
	MWMover__CreateMessage *message =
		Cast_Pointer(
			MWMover__CreateMessage*,
			message_stream->GetPointer()
		);
	message->messageLength = sizeof(*message);

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

	//
	//----------------------
	// Set up the joint name
	//----------------------
	//
	const char* instance_name = page->GetName();
	Str_Copy(
		message->jointName,
		instance_name,
		sizeof(message->jointName)
	);

	//
	//-------------------------------------------------------------
	// Look for the prop stream resource to see if it is up to date
	//-------------------------------------------------------------
	//
	MString armature_name = instance_file->GetFileName();
	armature_name += "[";
	armature_name += instance_name;
	armature_name += "]{armature}";
	Resource armature_resource(armature_name);

	MString sites_name = instance_file->GetFileName();
	sites_name += "[";
	sites_name += instance_name;
	sites_name += "]{sites}";
	Resource sites_resource(sites_name);

	if (
		armature_resource.DoesResourceExist() &&
		armature_resource.IsResourceUpToDate()
	)
	{
		WORD span;
		armature_resource >> span;
		Verify(span > 0);
		*script->baseID += span;
		message->replicatorID += span;
		message->armatureStreamResourceID = armature_resource.GetResourceID();
		message->siteStreamResourceID = sites_resource.GetResourceID();
		if (!armature_resource.IsRegistered())
			armature_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
		if (!sites_resource.IsRegistered())
			sites_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
	}

	//
	//---------------------------------------
	// For each page, an entity will be built
	//---------------------------------------
	//
	else
	{
		FileDependencies arm_deps(*instance_file->GetFileDependencies());
		FileDependencies *parent = Resource::ParentFileDependencies;
		Resource::ParentFileDependencies = &arm_deps;
		DynamicMemoryStream armature_stream(sizeof(WORD));
		DynamicMemoryStream site_stream;
		armature_stream << static_cast<WORD>(0);
		ReplicatorID starting_id = *script->baseID;
		ChainOf<Note*> *instances = page->MakeNoteChain("Child");
		Check_Object(instances);
		Page::NoteIterator instance_names(instances);
		Note *instance;
		while ((instance = instance_names.ReadAndNext()) != NULL)
		{
			Check_Object(instance);

			//
			//--------------------------------
			// Create the entity for this page
			//--------------------------------
			//
			const char* child_name;
			instance->GetEntry(&child_name);
			Check_Pointer(child_name);
			Page *child_page = instance_file->GetPage(child_name);
			Check_Object(child_page);

			//
			//------------------------------------
			//Check if a site, but not the eyesite
			//------------------------------------
			//

			//strstr is case sensative so make our name all lower case
			char *child_all_lower = _strlwr((char *)child_name);

			if((strstr(child_all_lower, "site_")) &&
				(!strstr(child_all_lower, "site_eye")))
			{
				YawPitchRoll rotation;
				Point3D translation;
				MString site_name = child_all_lower;
				child_page->GetEntry("Rotation", &rotation);
				child_page->GetEntry("Translation", &translation);

				site_stream << rotation;
				site_stream << translation;
				site_stream << site_name;


			

				if((!stricmp(child_all_lower, "site_lfoot")) ||
					(!stricmp(child_all_lower, "site_rfoot")))
				{
					//Jerry this will get deleted when you fix your foot problem
					SPEW(("jerryeds", "Check This out"));

					Entity::CreateMessage *message =
						Tool::Instance->ConstructCreateMessage(
							&armature_stream,
							child_page,
							script->baseID
						);
					Check_Object(message);
					armature_stream.AdvancePointer(message->messageLength);
				}
			}
			else
			{
				//
				//--------------
				//We are a joint
				//--------------
				//
				Entity::CreateMessage *message =
					Tool::Instance->ConstructCreateMessage(
						&armature_stream,
						child_page,
						script->baseID
					);
				Check_Object(message);
				armature_stream.AdvancePointer(message->messageLength);
			}
		}

		//
		//-----------------------------------------
		// Only save out the stream if there is one
		//-----------------------------------------
		//
		if (armature_stream.GetBytesUsed() > sizeof(WORD))
		{
			armature_stream.Rewind();
			Verify(*script->baseID != starting_id);
			WORD span =
				static_cast<WORD>(script->baseID->localID - starting_id.localID);
			armature_stream << span;
			armature_resource.Save(&armature_stream, &arm_deps);
			Check_Object(&armature_resource);
			message->armatureStreamResourceID = armature_resource.GetResourceID();
			message->replicatorID += span;
		}
		else
			message->armatureStreamResourceID = ResourceID::Null;

		//
		//----------------------------------------------
		// Only save out the site stream if there is one
		//----------------------------------------------
		//
		if (site_stream.GetBytesUsed() > 0.0f)
		{
			sites_resource.Save(&site_stream, &arm_deps);
			Check_Object(&sites_resource);
			message->siteStreamResourceID = sites_resource.GetResourceID();
		}
		else
			message->siteStreamResourceID = ResourceID::Null;


		if (!armature_resource.IsRegistered())
			parent->AddDependencies(&arm_deps);
		Resource::ParentFileDependencies = parent;

		//
		//------------------------
		// Clean up the tool stack
		//------------------------
		//
		Unregister_Object(instances);
		delete instances;
	}
	Tool::Instance->PopFilePath();
	Verify(stack_level == Tool::Instance->GetStackLevel());
}

void
	MWMover::SaveInstanceText(Page *page)
{
	Check_Object(this);
	Check_Object(page);


	BaseClass::SaveInstanceText(page);
	//
	//-------------------------
	// Save the Execution State
	//-------------------------
	//
	int execution_state = executionState->GetState();
	MString execution_state_text;
	switch(execution_state)
	{
	case ExecutionStateEngine::RegularMotionState:
		{
			execution_state_text = "RegularMotionState";
			break;
		}
	case ExecutionStateEngine::CameraMotionState:
		{
			execution_state_text = "CameraMotionState";
			break;
		}
	}
	if (execution_state_text)
	{
		page->SetEntry("ExecutionState", execution_state_text);
	}

}
