/*******************************************************************
*
*  DESCRIPTION: class Generator
*
*  AUTHOR: Amir Barylko & Jorge Beyoglonian 
*
*  EMAIL: mailto://amir@dc.uba.ar
*         mailto://jbeyoglo@dc.uba.ar
*
*  DATE: 27/6/1998
*
*******************************************************************/

/** include files **/
#include "generat.h"       // base header
#include "message.h"       // class InternalMessage 
#include "mainsimu.h"      // class Simulator
#include "distri.h"        // class Distribution 
#include "strutil.h"       // str2Value( ... )
#include "Msg.h"

/*******************************************************************
* Function Name: Generator
* Description: constructor
********************************************************************/
Generator::Generator( const string &name )
: Atomic( name )
, out( addOutputPort( "out" ) )
{
	try
	{
		dist = Distribution::create( MainSimulator::Instance().getParameter( description(), "distribution" ) );
		MASSERT( dist ) ;
		for ( register int i = 0; i < dist->varCount(); i++ )
		{
			string parameter( MainSimulator::Instance().getParameter( description(), dist->getVar( i ) ) ) ;
			dist->setVar( i, str2Value( parameter ) ) ;
		}

		if( MainSimulator::Instance().existsParameter( description(), "initial" ) )
			initial = str2Int( MainSimulator::Instance().getParameter( description(), "initial" ) );
		else
			initial = 0;

		if( MainSimulator::Instance().existsParameter( description(), "increment" ) )
			increment = str2Int( MainSimulator::Instance().getParameter( description(), "increment" ) );
		else
			increment = 1;

	} catch( InvalidDistribution &e )
	{
		e.addText( "The model " + description() + " has distribution problems!" ) ;
		e.print(cerr);
		MTHROW( e ) ;
	} catch( MException &e )
	{
		MTHROW( e ) ;
	}
}

/*******************************************************************
* Function Name: initFunction
********************************************************************/
Model &Generator::initFunction()
{
	pid = initial;
	holdIn( active, Time::Zero ) ;
	return *this ;
}

/*******************************************************************
* Function Name: internalFunction
********************************************************************/
Model &Generator::internalFunction( const InternalMessage & )
{
	holdIn( active, Time( static_cast< float >( fabs( distribution().get() ) ) ) ) ;
	return *this ;
}

/*******************************************************************
* Function Name: outputFunction
********************************************************************/
Model &Generator::outputFunction( const InternalMessage &msg )
{
	sendOutput( msg.time(), out, pid, NULL ) ;
	pid += increment;
	return *this ;
}

Generator::~Generator()
{
	delete dist;
}
