#include "munga.h"
#pragma hdrstop

#include "tool.h"
#include "fileutil.h"
#include "dropzone.h"
#include "camship.h"
#include "doorfram.h"
#include "eyecandy.h"
#include "explode.h"
#include "gaugalrm.h"
#include "cultural.h"
#include "scnrole.h"
#include "namelist.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ApplicationTool::CreateModelResource(
		ModelData &model_resources,
		const char *model_class,
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories *directories
	)
{
	if (!stricmp(model_class,"CameraShipClassID"))
	{
		model_resources.subsystemResourceID =
			CameraShip::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
	else if (!stricmp(model_class,"DoorFrameClassID"))
	{
		model_resources.subsystemResourceID =
			DoorFrame::CreateSubsystemStream(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
	else if(!stricmp(model_class,"EyeCandyClassID"))
	{
		model_resources.subsystemResourceID =
			EyeCandy::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
	else if(!stricmp(model_class,"ExplosionClassID"))
	{
		model_resources.gameResourceID =
			Explosion::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
	else if (!stricmp(model_class, "CulturalIconClassID"))
	{
		model_resources.gameResourceID =
			CulturalIcon::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
		model_resources.damageZoneResourceID =
			CulturalIcon::CreateDamageZoneStream(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
	else if (!stricmp(model_class, "LandmarkClassID"))
	{
		model_resources.gameResourceID =
			Landmark::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
		model_resources.damageZoneResourceID =
			Landmark::CreateDamageZoneStream(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
   else if(!stricmp(model_class,"ScenarioRoleClassID"))
	{
		model_resources.gameResourceID =
			ScenarioRole::CreateModelResource(
				resource_file,
				model_name,
				model_file,
				directories
			);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	ApplicationTool::WriteModels(
		NotationFile *notation_file,
		NotationFile *ops_file,
		StreamableResourceFile *file,
		const char *model_name,
		const ResourceDirectories *resource_directories,
		int resource_id
	)
{
	//
	//------------------------------------------------
	// If model is already in resource then we're done
	//------------------------------------------------
	//
	ResourceDescription *res_description = file->FindResourceDescription(
		model_name,
		ResourceDescription::ModelListResourceType
	);
	if (res_description)
	{
		return True;
	}

	//
	//----------------------------------------
	// Initialize model data and ops file info
	//----------------------------------------
	//
	ModelData model;
	model.videoResourceID = -1;
	model.audioResourceID = -1;
	model.collisionID = -1;
	model.gameResourceID = -1;
	model.subsystemResourceID = -1;
	model.controlsMappingsResourceID = -1;
	model.skeletonResourceID = -1;
	model.damageZoneResourceID = -1;
	model.gaugeImageResourceID =-1;
	model.gaugeAlarmResourceID =-1;
	model.gaugeMissionReviewResourceID =-1;
	model.explosionTableResourceID = -1;

	const char *ops_name;
	ops_file->GetEntry("resource", "res name", &ops_name);

	//
	//------------------------------------------------
	// Find the geometry file and make an entry for it
	//------------------------------------------------
	//
	model.videoResourceID =
		platformTool->CreateModelVideoStreamResource(
			file,
			model_name,
			notation_file,
			resource_directories
		);

	//
	//--------------------------------------------------
	// Find the audio file and make and entry for it
	//--------------------------------------------------
	//
	model.audioResourceID =
		platformTool->CreateModelAudioStreamResource(
			file,
			model_name,
			notation_file,
			resource_directories
		);

	const char *model_class;
	if (notation_file->GetEntry("gamedata","class",&model_class))
	{
		CreateModelResource(
			model,
			model_class,
			file,
			model_name,
			notation_file,
			resource_directories
		);
	}

	//
	//----------------------------------------------
	// Find the animations and make entries for them
	//----------------------------------------------
	//

	char animation_name[200];

	if(notation_file->PageExists("animations"))
	{
		NameList *animationnames =
			notation_file->MakeEntryList("animations", "animation");
		Register_Object(animationnames);
		NameList::Entry *animationentry = animationnames->GetFirstEntry();

		while (animationentry)
		{
			strcpy(animation_name, animationentry->GetChar());

			char *filename2 =
				MakePathedFilename(
					resource_directories->animationDirectory,
					animation_name
				);
			Register_Pointer(filename2);

			if(verboseMode)
			{
				Tell("Opening Animation : " << filename2 << std::endl);
			}

			NotationFile *new_notation_file = new NotationFile(filename2);
			Register_Object(new_notation_file);


			labOnly |= new_notation_file->IsMarkedLabOnly();

			const char *anim_p = StripExtension(StripDirectory(animation_name));
			const char *temp_pointer = animationentry->GetName();

			if (new_notation_file->PageCount())
			{
				if(strstr(temp_pointer, "transition"))
				{

					if (verboseMode)
					{
						std::cout << "Type Transition" << std::endl;
					}

					if (!WriteAnimationTransition(new_notation_file, file, anim_p))
					{

						std::cout << "Error - Animation did not work : " << filename2 << std::endl;

					}
				}
				else
				{
					if(verboseMode)
					{
						std::cout << "Type Cycle" << std::endl;
					}
					if (!WriteAnimationCycle(new_notation_file, file, anim_p))
					{

						std::cout << "Error - Animation did not work : " << filename2 << std::endl;

					}
				}
			}
			else
			{
				 std::cout << filename2 << " does not exist " << std::endl;
			}

			Unregister_Pointer(filename2);
			delete filename2;

			Unregister_Object(new_notation_file);
			delete new_notation_file;

			animationentry = animationentry->GetNextEntry();
		}

		Unregister_Object(animationnames);
		delete animationnames;

	}

	//
	//--------------------------------------------------
	// Find the collision file and make and entry for it
	//--------------------------------------------------
	//
	const char *entry_data;
	if (notation_file->GetEntry("collision","name",&entry_data))
	{
		Check_Pointer(entry_data);

		Logical convert_boxes = False;
		const char *dummy;

		if (notation_file->GetEntry("collision","convertboxes",&dummy))
		{
			convert_boxes = True;
		}
		else if (!stricmp(model_class, "LandmarkClassID"))
		{
			convert_boxes = True;
		}
		else if(!stricmp(model_class,"CulturalIconClassID"))
		{
			convert_boxes = True;
		}


		model.collisionID =
			BoxedSolidResource::CreateBoxedSolidStream(
				entry_data,
				file,
				resource_directories,
				convert_boxes
			);
	}

	//
	//-------------------------------------------------------------------
	// Find the controls mapping page and build a list of all the control
	// mappings there
	//-------------------------------------------------------------------
	//
	if (notation_file->PageExists("ControlMappings"))
	{
		NameList *mapping_list = notation_file->MakeEntryList("ControlMappings");
		Register_Object(mapping_list);
		NameList::Entry *entry = mapping_list->GetFirstEntry();

		//
		//-----------------------------------------------------------------------
		// Count the number of mapping files, and build a list big enough to hold
		// all of the mappings
		//-----------------------------------------------------------------------
		//
		int count=0;
		while (entry)
		{
			++count;
			entry = entry->GetNextEntry();
		}
		if (!count)
		{
			Unregister_Object(mapping_list);
			delete mapping_list;
			goto Make_Directory;
		}
		ResourceDescription::ResourceID *mappings =
			new ResourceDescription::ResourceID[count];
		Register_Pointer(mappings);

		//
		//-------------------------------------------------------------------
		// Step through the list, reading each of the specified control files
		//-------------------------------------------------------------------
		//
		entry = mapping_list->GetFirstEntry();
		count = 0;
		while (entry)
		{
			mappings[count] = -1;
			char *ctl_filename =
				MakePathedFilename(
					resource_directories->modelDirectory,
					entry->GetChar()
				);
			Register_Pointer(ctl_filename);

			NotationFile *ctl_file = new NotationFile(ctl_filename);
			Register_Object(ctl_file);
			if (!ctl_file->PageCount())
			{
				std::cout << model_name << " unable to open " << ctl_filename << "!\n";
Unwind_1:
				Unregister_Object(ctl_file);
				delete ctl_file;
				Unregister_Pointer(ctl_filename);
				delete[] ctl_filename;
				Unregister_Pointer(mappings);
				delete[] mappings;
				Unregister_Object(mapping_list);
				delete mapping_list;
				goto Make_Directory;
			}

			//
			//-----------------------------
			// Find out which model to call
			//-----------------------------
			//
			mappings[count] =
				CreateControlMappingStream(
					model_class,
					entry->GetName(),
					ctl_file,
					file,
					model_name,
					notation_file,
					resource_directories,
					platformTool
				);
			if (mappings[count] == -1)
			{
				std::cout << model_name << " unable to process " << entry->GetName()
				 << " control mapping!\n";
				goto Unwind_1;
			}
			Unregister_Object(ctl_file);
			delete ctl_file;
			Unregister_Pointer(ctl_filename);
			delete[] ctl_filename;
			++count;
			entry = entry->GetNextEntry();
		}

		res_description = file->AddResourceList(
			model_name,
			ResourceDescription::ControlMappingsListResourceType,
			1,
			ResourceDescription::LoadOnDemandFlag,
			mappings,
			count
		);


		Verify(res_description);
		model.controlsMappingsResourceID = res_description->resourceID;
		Unregister_Object(mapping_list);
		Unregister_Pointer(mappings);
		delete mapping_list;
		delete[] mappings;
	}
	//
	//-------------------------------------------------------------------
	// Find the gaugeMissionReview page and save the pertinent data
	//-------------------------------------------------------------------
	//
	model.gaugeMissionReviewResourceID =
		platformTool->CreateModelGaugeMissionReviewStreamResource(
			file,
			model_name,
			notation_file,
			resource_directories
		);
	//
	//-----------------------------------------------
	//  Find GaugeImage File and make an entry for it
	//-----------------------------------------------
	//
	model.gaugeImageResourceID =
		platformTool->CreateModelGaugeImageStreamResource(
			file,
			model_name,
			notation_file,
			resource_directories
		);
	//
	//------------------------------------------------
	//  Find Gauge alarm file and make an entry for it
	//------------------------------------------------
	//
	{
		GaugeAlarmManager
			*gaugeAlarmManager = platformTool->gaugeAlarmManager;

		if (gaugeAlarmManager == NULL)
		{
			model.gaugeAlarmResourceID = -1;
		}
		else
		{
			Check(gaugeAlarmManager);

			model.gaugeAlarmResourceID =
				gaugeAlarmManager->CreateModelGaugeAlarmStreamResource(
					file,
					model_name,
					notation_file,
					resource_directories
				);
      }
	}
	//
	//-------------------------------------------
	// Make a directory for the model information
	//-------------------------------------------
	//
Make_Directory:
	int *model_data = new int[20];
	Register_Pointer(model_data);
	int i = 0;
	if (model.videoResourceID >= 0)
	{
		model_data[i++] = model.videoResourceID;
	}
	if (model.audioResourceID >= 0)
	{
		model_data[i++] = model.audioResourceID;
	}
	if (model.collisionID >= 0)
	{
		model_data[i++] = model.collisionID;
	}
	if (model.gameResourceID >= 0)
	{
		model_data[i++] = model.gameResourceID;
	}
	if (model.subsystemResourceID >= 0)
	{
		model_data[i++] = model.subsystemResourceID;
	}
	if (model.skeletonResourceID >= 0)
	{
		model_data[i++] = model.skeletonResourceID;
	}
	if (model.controlsMappingsResourceID >= 0)
	{
		model_data[i++] = model.controlsMappingsResourceID;
	}
	if (model.damageZoneResourceID >= 0)
	{
		model_data[i++] = model.damageZoneResourceID;
	}
	if (model.gaugeImageResourceID >= 0)
	{
		model_data[i++] = model.gaugeImageResourceID;
	}
	if (model.gaugeAlarmResourceID >= 0)
	{
		model_data[i++] = model.gaugeAlarmResourceID;
	}
	if (model.gaugeMissionReviewResourceID >= 0)
	{
		model_data[i++] = model.gaugeMissionReviewResourceID;
	}
	if (model.explosionTableResourceID >= 0)
	{
		model_data[i++] = model.explosionTableResourceID;
	}

	res_description =
		file->FindResourceDescription(
			model_name,
			ResourceDescription::ModelListResourceType
		);

	if (!res_description)
	{
		if (i > 0)
		{
			if (resource_id == -1)
			{
				file->AddResourceList(
					model_name,
					ResourceDescription::ModelListResourceType,
					1,
					ResourceDescription::Preload,
					model_data,
					i
				);
			}
			else
			{

				ResourceDescription
					*res_des = file->FindResourceDescription(resource_id);

				if (!res_des)
				{
					file->AddResourceList(
						model_name,
						ResourceDescription::ModelListResourceType,
						1,
						ResourceDescription::Preload,
						model_data,
						i,
						resource_id
					);
				}
				else
				{
					DEBUG_STREAM << model_name << " : " << resource_id << std::endl << std::flush;
					Fail("Duplicate Resource Number");
				}
			}
		}
		else
		{
			if (resource_id == -1)
			{
				file->AddResource(
					model_name,
					ResourceDescription::ModelListResourceType,
					1,
					ResourceDescription::Preload,
					&i,
					sizeof(i)
				);
			}
			else
			{
				 ResourceDescription
					*res_des = file->FindResourceDescription(resource_id);

				 if (!res_des)
				 {
					file->AddResource(
						model_name,
						ResourceDescription::ModelListResourceType,
						1,
						ResourceDescription::Preload,
						&i,
						sizeof(i),
						resource_id
					);
				}
				else
				{
					DEBUG_STREAM << model_name << " : " << resource_id << std::endl << std::flush;
					Fail("Duplicate Resource Number");
				}
			}
		}
	}
	Unregister_Pointer(model_data);
	delete model_data;
	return True;
}
