/*******************************************************************
*
*  DESCRIPTION: class Model(base class for Amtomic and Coupled)
*
*  AUTHOR:    Amir Barylko & Jorge Boyoglonian 
*  Version 2: Daniel Rodriguez
*
*  EMAIL: mailto://amir@dc.uba.ar
*         mailto://jbeyoglo@dc.uba.ar
*         mailto://drodrigu@dc.uba.ar
*
*  DATE: 27/6/1998
*  DATE: 27/2/1999 (v2)
*
*******************************************************************/

#ifndef __MODEL_H
#define __MODEL_H

/** include files **/
#include <string>    // Template string
#include "port.h"     // class Port 
#include "time.h"     // class Time
#include "portlist.h"
#include "procadm.h"

/** foward declarations **/

class ModelAdmin ;
class MessageAdmin ;
class Coupled ;
class Root ; 
class Simulator ;
class Processor ;
class Coordinator ;
class SendPortNode ;

/** definitions **/

#define	MODEL_NAME	"Model"

class Model
{
public:
	virtual ~Model();	// Destructor

	virtual string className() const = 0;

	virtual Port &addInputPort( const string & );
	virtual Port &addOutputPort( const string & );

	virtual const PortList &inputPorts() const
			{return inputList;}

	virtual const PortList &outputPorts() const
			{return outputList;}

	Port & port( const string & );

	const Time &nextChange() const
		{return SingleProcessorAdmin::Instance().processor( id() ).nextChange();}

	const Time &lastChange() const
			{return SingleProcessorAdmin::Instance().processor( id() ).lastChange();}

	const ModelId &id() const
			{return ident;}

	const string asString() const
			{return description() + "(" + id() + ")";}

	const Time absoluteNext() const
			{return lastChange() + nextChange();}

	virtual PortList &inputPorts()
			{return inputList;}
			
	virtual PortList &outputPorts()
			{return outputList;}

	const ModelId &parentId() const
			{return parent_id;}
			
	Model &parentId( const ModelId &mid )
			{parent_id = mid; return *this;}

	const Model &parent() const
			{return SingleProcessorAdmin::Instance().processor( parentId() ).model();}

	Model &parent( const Model &p )
			{parent_id = p.id(); return *this;}

	const string &description() const
			{return descript;}

	bool operator <( const Model &model ) const
			{return this->id() < model.id();}

protected:

	friend class Processor ;
	friend class Simulator ;
	friend class Coordinator ;
	friend class SendPortNode ;

	Model( const string &name = "Model" ) ; // Default constructor

	Model &nextChange( const Time & );
	Model &lastChange( const Time & );

	Model &id( const ModelId &mid )
			{ident = mid; return *this;}

	Model &sendOutput( const Time &time, const Port &port, const Value &value, ValueO *valueO)
			{processor().sendOutput( time, port, value, valueO ); return *this;}

	Processor &processor()
			{return SingleProcessorAdmin::Instance().processor( id() );}

private:
	friend class ModelAdmin ;
	friend class MessageAdmin ;
	friend class Coupled ;
	friend class Root ;

	ModelId ident ;
	ModelId parent_id ;
	string descript ;

	PortList inputList ;
	PortList outputList ;

};	// class Model


#endif   //__MODEL_H 
