//===========================================================================//
// File:	VehicleInterface_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 "VehicleInterface.hpp"
#include "MWTool.hpp"
#include "MWGUIManager.hpp"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	VehicleInterface__CreateMessage::ConstructCreateMessage(Script *script)
{
	Check_Object(script);

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

	//
	//---------------------------
	// Point at the notation file
	//---------------------------
	//
	Page *page = script->instancePage;
	Check_Object(page);
	Check_Object(Tool::Instance);
	
	//
	//----------------------------------
	//Create the GUI (This is temporary)
	//----------------------------------
	//
	NotationFile gui_file;
	message->guiStreamResourceID = ResourceID::Null;
	if (page->GetEntry("GUIContents", &gui_file))
	{
		//
		//-------------------------------------------------------------
		// Look for the gui stream resource to see if it is up to date
		//-------------------------------------------------------------
		//
		const char *gui_file_name = gui_file.GetFileName();
		Check_Pointer(gui_file_name);
		Resource gui_resource(gui_file_name);
		if (
			gui_resource.DoesResourceExist() &&
			gui_resource.IsResourceUpToDate()
		)
		{
			message->guiStreamResourceID = gui_resource.GetResourceID();
			if (!gui_resource.IsRegistered())
				gui_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
		}
		else
		{
			FileDependencies gui_deps(*gui_file.GetFileDependencies());
			FileDependencies *parent = Resource::ParentFileDependencies;
			Resource::ParentFileDependencies = &gui_deps;

			if (MWGUIManager::GetInstance() != NULL)
			{
				Check_Object(MWGUIManager::GetInstance());
			//	MWGUIManager::GetInstance()->ReadObjectsFromNotation(gui_file);
				DynamicMemoryStream gui_stream;
			//	MWGUIManager::GetInstance()->SaveObjectsToStream(&gui_stream);
				MWGUIManager::GetInstance()->WriteObjectsFromFileToStream(&gui_file, &gui_stream);
				if (gui_stream.GetBytesUsed())
				{
					gui_resource.Save(&gui_stream, &gui_deps);
					Check_Object(&gui_resource);
					message->guiStreamResourceID = gui_resource.GetResourceID();
					if (!gui_resource.IsRegistered())
						gui_resource.AddFileDependenciesTo(&gui_deps);
				}
				else
				{
					message->guiStreamResourceID = ResourceID::Null;
				}
			}
			Resource::ParentFileDependencies = parent;
		}
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	VehicleInterface__GameModel::ConstructGameModel(Script *script)
{
	Check_Object(script);

	//
	//--------------
	// Set up stream
	//--------------
	//
	MemoryStream *model_stream = script->modelStream;
	Check_Object(model_stream);
	model_stream->AllocateBytes(sizeof(VehicleInterface__GameModel));
	BaseClass::ConstructGameModel(script);
	
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	VehicleInterface__GameModel::ReadAndVerify(
		VehicleInterface__GameModel *model,
		ModelAttributeEntry *attribute_entry, 
		const char *data,
		char **error,
		int error_buffer
	)
{
	Check_Object(attribute_entry);

	bool result = false;
	bool valid_data = (*data != '\0');

	//
	//----------------------------------------
	//Read in the values from the data entered
	//----------------------------------------
	//
	result = 
		BaseClass::ReadAndVerify(
			model, 
			attribute_entry, 
			data,
			error,
			error_buffer
		);
	//
	//---------------------------
	//Verify all the model values
	//---------------------------
	//
	switch(attribute_entry->attributeID)
	{
	case BRBModeAttributeID:
		{
			if(!valid_data)
			{
				int value = 0;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->brbMode < 0)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]BRBMode=%f}: value must be >= 0!",
					model->brbMode
				);
				result = false;
			}
			break;
		}
	case CameraStartOffsetAttributeID:
		{
			if(!valid_data)
			{
				Vector3D value = Vector3D::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}
	case CameraExternalTargetStartOffset1AttributeID:
		{
			if(!valid_data)
			{
				Vector3D value = Vector3D::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}
	case CameraExternalTargetStartOffset2AttributeID:
		{
			if(!valid_data)
			{
				Vector3D value = Vector3D::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}
	case CameraExternalTargetStartOffset3AttributeID:
		{
			if(!valid_data)
			{
				Vector3D value = Vector3D::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}
	case CameraStartAngleAttributeID:
		{
			if(!valid_data)
			{
				UnitQuaternion value = UnitQuaternion::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			break;
		}

	case MaxTargetDistanceAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 1000.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->maxTargetDistance <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MaxTargetDistance=%f}: value must be > 0!",
					model->maxTargetDistance
				);
			}
			break;
		}
	case TurnSpeedZoomModifierYawAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 3.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->turnSpeedZoomModifierYaw <= 0.0f || Small_Enough(model->turnSpeedZoomModifierYaw) || 
				 model->turnSpeedZoomModifierYaw >= 10.0f)
			{
				model->turnSpeedZoomModifierYaw = 1.0f / 3.0f;
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TurnSpeedZoomModifierYaw=%f}: value must be > 0!",
					model->turnSpeedZoomModifierYaw
				);
			}
			else
			{
				model->turnSpeedZoomModifierYaw = 1.0f / model->turnSpeedZoomModifierYaw;
			}
			break;
		}
	case TurnSpeedZoomModifierPitchAttributeID:
		{
			if(!valid_data)
			{
				Scalar value =  3.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->turnSpeedZoomModifierPitch <= 0.0f || Small_Enough(model->turnSpeedZoomModifierPitch) || 
				 model->turnSpeedZoomModifierPitch >= 10.0f)
			{
				model->turnSpeedZoomModifierPitch = 1.0f / 3.0f;
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TurnSpeedZoomModifierPitch=%f}: value must be > 0!",
					model->turnSpeedZoomModifierPitch
				);
			}
			else
			{
				model->turnSpeedZoomModifierPitch = 1.0f / model->turnSpeedZoomModifierPitch;
			}
			break;
		}
	case TurnSpeedZoomModifierTorsoAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 3.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->turnSpeedZoomModifierTorso <= 0.0f || Small_Enough(model->turnSpeedZoomModifierTorso) || 
				 model->turnSpeedZoomModifierTorso >= 10.0f)
			{
				model->turnSpeedZoomModifierTorso = 1.0f / 3.0f;
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TurnSpeedZoomModifierTorso=%f}: value must be > 0!",
					model->turnSpeedZoomModifierTorso
				);
			}
			else
			{
				model->turnSpeedZoomModifierTorso = 1.0f / model->turnSpeedZoomModifierTorso;
			}
			break;
		}
	case RotationPerSecondAttributeID:
		{
			if(!valid_data)
			{
				Radian value;
				value.angle = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->rotationPerSecond.angle <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]RotationPerSecond=%f}: value must be > 0!",
					model->rotationPerSecond.angle
				);
			}
			break;
		}
	case TranslationPerSecondAttributeID:
		{
			if(!valid_data)
			{
				Point3D value = Point3D::Identity;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->translationPerSecond.x <= 0.0f || model->translationPerSecond.y <= 0.0f || model->translationPerSecond.z <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]TranslationPerSecond=%f %f %f}: values must be > 0!",
					model->translationPerSecond.x,
					model->translationPerSecond.y,
					model->translationPerSecond.z
				);
			}
			break;
		}

	case DeathTimerAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->deathTimer <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DeathTimer=%f}: value must be > 0!",
					model->deathTimer
				);
			}
			break;
		}
	case DelayTorsoCenterAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->delayTorsoCenter <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]DelayTorsoCenter=%f}: value must be >= 0!",
					model->deathTimer
				);
			}
			break;
		}
	case MaxSpeedAboveMinTransToTorsoCenterKPHAttributeID:
		{
			if(!valid_data)
			{
				Scalar value = 0.0f;
				attribute_entry->SetValue(model, &value);
				result = true;
			}
			if(model->maxSpeedAboveMinTransToTorsoCenterKPH <= 0.0f)
			{
				_snprintf(
					*error,
					error_buffer,
					"{[GameData]MaxSpeedAboveMinTransToTorsoCenterKPH=%f}: value must be >= 0!",
					model->deathTimer
				);
			}
			break;
		}
	case PlayerAIResourceAttributeID:
		{
			if(!valid_data)
			{
				ResourceID value = ResourceID::Null;
				attribute_entry->SetValue(model, (void *)&value);
				result = true;
			}
			break;
		}

	}
	return result;
}