#include "munga.h"
#pragma hdrstop

#include "random.h"
#include "eyecandy.h"
#include "app.h"
#include "notation.h"

//#############################################################################
// Shared Data Support
//
EyeCandy::SharedData
	EyeCandy::DefaultData(
		EyeCandy::GetClassDerivations(),
		EyeCandy::GetMessageHandlers(),
		EyeCandy::GetAttributeIndex(),
		EyeCandy::StateCount,
		(Entity::MakeHandler)EyeCandy::Make
	);

Derivation* EyeCandy::GetClassDerivations()
{
	static Derivation classDerivations(Entity::GetClassDerivations(), "EyeCandy");
	return &classDerivations;
}

//#############################################################################
//###############################    EyeCandy    #################################
//#############################################################################

void
	EyeCandy::EyeCandySimulation(Scalar)
{
	Check(application);

	if (simulationState.GetState() == effectOn)
	{
		simulationState.SetState(effectOff);
	}

	Scalar now = Now();
	if ((now - lastTrigger) >= waitTime)
	{
		simulationState.SetState(effectOn);
		lastTrigger = now;

		RandomGenerator random_number;
		waitTime = minWaitTime + (maxWaitTime - minWaitTime) * random_number;
	}
}

//#############################################################################
// Construction and Destruction
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EyeCandy::EyeCandy(
	EyeCandy::MakeMessage *creation_message ,
	EyeCandy::SharedData &virtual_data
):
	Entity(creation_message, virtual_data)
{
	Check_Pointer(this);
	Check_Pointer(creation_message);
	SetPerformance(&EyeCandy::EyeCandySimulation);
	SetValidFlag();

	//
	//-------------------------------------------------
	// Find the EyeCandy in the resource
	//-------------------------------------------------
	//
	ResourceFile *res_file = application->GetResourceFile();
	Check(res_file);
	ResourceDescription *res =
		res_file->SearchList(
			resourceID,
			ResourceDescription::GameModelResourceType
		);
	Check(res);
	res->Lock();

	ModelResource *eyecandy_res = (ModelResource*)res->resourceAddress;
	maxWaitTime = eyecandy_res->maxWaitTime;
	minWaitTime = eyecandy_res->minWaitTime;
	res->Unlock();

	waitTime = minWaitTime + (maxWaitTime - minWaitTime) * Random;

	simulationState.SetState(effectOff);
	lastTrigger = Now();


}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EyeCandy*
	EyeCandy::Make(EyeCandy::MakeMessage *creation_message)
{
	return new EyeCandy(creation_message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	EyeCandy::CreateMakeMessage(
		MakeMessage *creation_message,
		NotationFile *model_file,
		const ResourceDirectories *directories
	)
{
	Check(creation_message);
	Check(model_file);

	if (!Entity::CreateMakeMessage(creation_message, model_file, directories))
	{
		return False;
	}

	creation_message->classToCreate = RegisteredClass::EyeCandyClassID;
	creation_message->instanceFlags = HermitInstance|DynamicFlag|TrappedFlag;
	return True;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EyeCandy::~EyeCandy()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

ResourceDescription::ResourceID
	EyeCandy::CreateModelResource(
#if DEBUG_LEVEL>0
		ResourceFile *resource_file,
		const char* model_name,
		NotationFile * model_file,
		const ResourceDirectories *directories,
		ModelResource *model
#else
		ResourceFile *resource_file,
		const char* model_name,
		NotationFile * model_file,
		const ResourceDirectories *,
		ModelResource *model
#endif
	)
{
	Check(resource_file);
	Check_Pointer(model_name);
	Check_Pointer(directories);

	//
	// If we were not provided a buffer to write the model data into, we must
	// create it ourselves.  Then make sure that the model stuff is read in
	//
	ModelResource *local_model = model;
	if (!local_model)
	{
		local_model = new ModelResource;
		Register_Pointer(local_model);
	}

	//----------------------------------------
	//  Read in the data from notation file
	//----------------------------------------
	//
	// Get PointValue assigned to this ScoreZone
	//

	if(
	!model_file->GetEntry(
		"gamedata",
		"MaxWaitTime",
		&local_model->maxWaitTime
		)
	)
	{
		std::cerr << model_name <<  "Missing MaxWaitTime" <<  std::endl;
Dump_And_Die:
		if (!model)
		{
			Unregister_Pointer(local_model);
			delete local_model;
		}
		return -1;
	}

	if(
	!model_file->GetEntry(
		"gamedata",
		"MinWaitTime",
		&local_model->minWaitTime
		)
	)
	{
		std::cerr << model_name <<  "Missing MinWaitTime" << std::endl;
		goto Dump_And_Die;
	}

	//
	//---------------------------
	// Write out the new resource
	//---------------------------
	//
	if (!model)
	{
		ResourceDescription *new_res =
			resource_file->AddResource(
				model_name,
				ResourceDescription::GameModelResourceType,
				1,
				ResourceDescription::Preload,
				local_model,
				sizeof(*local_model)
			);
		Unregister_Pointer(local_model);
		delete local_model;
		Check(new_res);
		return new_res->resourceID;
	}
	else
	{
		return 0;
	}
}

Logical
	EyeCandy::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}
