//===========================================================================//
// File:	gaugalrm.cpp                                                        //
// Project: MUNGA           Brick: Gauge Renderer Manager	                 //
// Contents: 																					  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/22/96  CPB  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved //
//                      PROPRIETARY and CONFIDENTIAL                         //
//===========================================================================//

#include <munga.hpp>
#pragma hdrstop

#if !defined(GAUGALRM_HPP)
#	include <gaugalrm.hpp>
#endif

#if !defined(APP_HPP)
#	include <app.hpp>
#endif

#if !defined(NOTATION_HPP)
#	include <notation.hpp>
#endif

#if !defined(NAMELIST_HPP)
#	include <namelist.hpp>
#endif

#if !defined(ENTITY_HPP)
#	include <entity.hpp>
#endif

#if !defined(SUBSYSTM_HPP)
#	include <subsystm.hpp>
#endif

// #define LOCAL_TEST

#if defined(LOCAL_TEST)
#	define Test_Tell(n) DEBUG_STREAM << n
#else
#	define Test_Tell(n)
#endif

//#######################################################################
// GaugeAlarm
//#######################################################################
GaugeAlarm::GaugeAlarm(
	Entity *the_entity,
	Subsystem *the_subsystem,
	Enumeration the_condition
) :
	Node(RegisteredClass::GaugeAlarmClassID),
	lampList(NULL)
{
	Check(the_entity);
	Check(the_subsystem);

	Test_Tell(
		"GaugeAlarm(" << the_entity <<
		", " << the_subsystem <<
		", " << the_condition <<
		")\n"
	);

	entity = the_entity;
	subsystem = the_subsystem;
	conditionIndex = the_condition;
	Check_Fpu();
}

GaugeAlarm::~GaugeAlarm()
{
	Test_Tell("~GaugeAlarm()");
	Check(this);

	ChainIteratorOf<Lamp*>
		i(lampList);
	Lamp
		*lamp_pointer;

	while ((lamp_pointer=i.ReadAndNext()) != NULL)
	{
		Check(lamp_pointer);
		Test_Tell("lamp ");
		lamp_pointer->SetAlertState(False);
	}
	Test_Tell("\n");
	Check_Fpu();
}

Logical
	GaugeAlarm::TestInstance() const
{
	return Node::TestInstance();
}


//#######################################################################
// GaugeAlarmManager
//#######################################################################
Logical
	GaugeAlarmManager::CreateGaugeAlarmStreamItem(
		MemoryStream */*mem_stream*/,
		const char */*alarm_name*/,
		const char */*alarm_data*/
	)
{
	Fail("GaugeAlarmManager::CreateGaugeAlarmStreamItem not overridden!");
	return False;
}

void
	GaugeAlarmManager::ReadGaugeAlarmStreamItem(
		GaugeAlarm */*alarm*/,
		Entity */*the_entity*/,
		Subsystem */*the_subsystem*/,
		Enumeration /*the_condition*/,
		MemoryStream */*mem_stream*/
	)
{
	Fail("GaugeAlarmManager::ReadGaugeAlarmStreamItem not overridden!");
}

ResourceDescription::ResourceID
	GaugeAlarmManager::CreateModelGaugeAlarmStreamResource(
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories */*directories*/
	)
{
	Check(resource_file);
	Check_Pointer(model_name);
	Check(model_file);

	int
		i;
	ResourceDescription::ResourceID
		res_id = ResourceDescription::NullResourceID;

	//-------------------------------------------------------------
	// Make sure the notation file is in relaxed operation mode
	//-------------------------------------------------------------
	Enumeration
		old_notation_file_mode = model_file->GetModes();

	model_file->SetMode(
		NotationFile::RelaxedOperationModes | NotationFile::SkipBlanksListMode
	);
	//-------------------------------------------------------------
	// Build a list of all the alarm entries for the gauge renderer
	//-------------------------------------------------------------
	NameList
		*alarm_list = model_file->MakeEntryList("gaugeAlarm");

	if (alarm_list != NULL)
	{
		Test_Tell(
			"Processing model gauge alarm data for '" << model_name << "':"
		);
		Register_Object(alarm_list);
		//-------------------------------------------------------------
		//	Get the number of alarms
		//-------------------------------------------------------------
		Logical
			built_ok = True;
		int
			alarm_count = alarm_list->EntryCount();

		Test_Tell(alarm_count << " entries.\n");
		Verify(alarm_count > 0);
		//-------------------------------------------------------------
		// Create a dynamic memory stream
		//-------------------------------------------------------------
		DynamicMemoryStream
			*alarm_stream = new DynamicMemoryStream();
		Register_Object(alarm_stream);
		//-------------------------------------------------------------
		//	Write the number of alarms to the stream
		//-------------------------------------------------------------
		MemoryStream_Write(alarm_stream, &alarm_count);
		//-------------------------------------------------------------
		//	Write the alarms to the stream
		//-------------------------------------------------------------
		NameList::Entry
			*alarm_entry = alarm_list->GetFirstEntry();

		for(i=0; i<alarm_count; ++i)
		{
			Verify(alarm_entry != NULL);

			if (
					CreateGaugeAlarmStreamItem(
						alarm_stream,
						alarm_entry->GetName(),
						alarm_entry->GetChar()
					)
					== False
				)
			{
				DEBUG_STREAM <<
					"Model file '" << model_name <<
					"' has undefined alarm type '" << alarm_entry->GetName() <<
					"' - resource not built.\n";
				built_ok = False;
				break;
			}
			alarm_entry = alarm_entry->GetNextEntry();
		}
		//-------------------------------------------------------------
		// Create the resource description, assign an ID
		//-------------------------------------------------------------
		if (built_ok)
		{
			Test_Tell("Creating resource description for '"<<model_name<<"'\n");

			ResourceDescription
				*res_desc_stream =
					resource_file->AddResourceMemoryStream(
						model_name,
						ResourceDescription::GaugeAlarmStreamResourceType,
						1,		// priority
						ResourceDescription::Preload,
						alarm_stream
					);

			Check(res_desc_stream);
			res_id = res_desc_stream->resourceID;
		}

		Unregister_Object(alarm_stream);
		delete alarm_stream;
		Test_Tell("Closed gauge alarm stream\n" << flush);
		Test_Tell("res_id = " << res_id << "\n");
	}
	//-------------------------------------------------------------
	// Restore the notation file's previous operation mode
	//-------------------------------------------------------------
	model_file->PutModes(old_notation_file_mode);
	//-------------------------------------------------------------
	// Return the new ResourceID
	//-------------------------------------------------------------
	Check_Fpu();
	return res_id;
}

GaugeAlarmManager::GaugeAlarmManager() :
	gaugeAlarmList(NULL)
{
	Check_Fpu();
}

GaugeAlarmManager::~GaugeAlarmManager()
{
	Check(this);
	Check_Fpu();
}

Logical
	GaugeAlarmManager::TestInstance() const
{
	return True;
}

void
	GaugeAlarmManager::RemoveAllAlarms()
{
	Check(this);

	//-------------------------------------------
	// Delete all GaugeAlarms
	//-------------------------------------------
	ChainIteratorOf<GaugeAlarm*>
		i(gaugeAlarmList);
	GaugeAlarm
		*alarm_pointer;

	while ((alarm_pointer=i.ReadAndNext()) != NULL)
	{
		Check(alarm_pointer);
		Unregister_Object(alarm_pointer);
		delete alarm_pointer;
	}
	Check_Fpu();
}

void
	GaugeAlarmManager::Activate(
		Entity *entity,
		Subsystem *subsystem,
		Enumeration condition,
		ResourceDescription::ResourceID new_resource_id
	)
{
	Test_Tell(
		"GaugeAlarmManager::Activate(" << entity <<
		", " << subsystem <<
		", " << condition <<
		", " << new_resource_id <<
		")\n";
	);
	Check(this);

	Check(application);
	Check(application->GetResourceFile());
	//-------------------------------------------
	// Attempt to find the specified resource
	//-------------------------------------------
	ResourceDescription
		*stream_resource_description =
			application->GetResourceFile()->SearchList(
				new_resource_id,
				ResourceDescription::GaugeAlarmStreamResourceType
			);

	if (stream_resource_description == NULL)
	{
		Test_Tell(
			"GaugeAlarmManager::Activate: resource ID '" << new_resource_id <<
			"' does not exist\n"
		); 
	}
	else
	{
		//-------------------------------------------
		// Lock the stream 
		//-------------------------------------------
		stream_resource_description->Lock();
		//-------------------------------------------
		// Found it, open a DynamicMemoryStream
		//-------------------------------------------
		DynamicMemoryStream
			*dynamic_memory_stream =
				new DynamicMemoryStream(
					stream_resource_description->resourceAddress,
					stream_resource_description->resourceSize
				);
		if (dynamic_memory_stream == NULL)
		{
			Test_Tell("GaugeAlarmManager::Activate: couldn't open stream\n"); 
		}
		else
		{
			Register_Object(dynamic_memory_stream);
			//-------------------------------------------
			// Create the object, add to alarm list
			//-------------------------------------------
			GaugeAlarm
				*alarm =	new GaugeAlarm(
					entity,
					subsystem,
					condition
				);
			Register_Object(alarm);
			gaugeAlarmList.Add(alarm);
			//-------------------------------------------
			//	Read the alarm items from the stream
			//-------------------------------------------
			int
				alarm_count;
			MemoryStream_Read(dynamic_memory_stream, &alarm_count);
			Verify(alarm_count > 0);

			for(; alarm_count>0; --alarm_count)
			{
				ReadGaugeAlarmStreamItem(
					alarm,
					entity,
					subsystem,
					condition,
					dynamic_memory_stream
				);
			}
			//-------------------------------------------
			// Destroy the stream
			//-------------------------------------------
			Unregister_Object(dynamic_memory_stream);
			delete dynamic_memory_stream;
		}
		//-------------------------------------------
		// Unlock the stream 
		//-------------------------------------------
		stream_resource_description->Unlock();
	}
	Check_Fpu();
}

void
	GaugeAlarmManager::Deactivate(
		Entity *entity,
		Subsystem *subsystem,
		Enumeration condition
	)
{
	Test_Tell(
		"GaugeAlarmManager::Deactivate(" << entity <<
		", " << subsystem <<
		", " << condition <<
		")\n";
	);
	Check(this);
	//-------------------------------------------
	// Find matching GaugeAlarm
	//-------------------------------------------
	ChainIteratorOf<GaugeAlarm*>
		i(gaugeAlarmList);
	GaugeAlarm
		*alarm_pointer;

	while ((alarm_pointer=i.ReadAndNext()) != NULL)
	{
		Check(alarm_pointer);
		Test_Tell("pointer=" << alarm_pointer);
		if (alarm_pointer->entity == entity)
		{
			if (alarm_pointer->subsystem == subsystem)
			{
				if (alarm_pointer->conditionIndex == condition)
				{
					Test_Tell("Found:");
					Unregister_Object(alarm_pointer);
					delete alarm_pointer;
					break;
				}
			}
		}
		Test_Tell("\n");
	}
	Check_Fpu();
}


