/*******************************************************************
*
*  DESCRIPTION: class AtomicCell (Abstract)
*
*  AUTHOR:    Amir Barylko, Jorge Beyoglonian
*  Version 2: Daniel Rodriguez.
*
*  EMAIL: mailto://amir@dc.uba.ar
*         mailto://jbeyoglo@dc.uba.ar
*         mailto://drodrigu@dc.uba.ar
*
*  DATE: 27/06/1998
*  DATE: 17/09/1999 (v2)
*
*******************************************************************/

#ifndef __ATOMIC_CELL_H
#define __ATOMIC_CELL_H

/** include files **/
#include "portlist.h"         // for the PortList definition
#include "atomic.h"           // base class
#include "neighval.h"         // NeighborhoodValue
#include "ltranadm.h"         // LocalTransAdmin
#include "cellpos.h"          // class CellPos and NeighborPosition
#include "real.h"             // The value of the cell

/** forward declarations **/
class CoupledCell ;
class MainSimulator ;

#define	ATOMIC_CELL_NAME		"AtomicCell"

/** declarations **/
class AtomicCell: public Atomic
{
public:
	~AtomicCell();

	virtual string className() const
		{ return ATOMIC_CELL_NAME; }

	AtomicCell &localFunction( const LocalTransAdmin::Function &lf )
		{ localFn = lf; return *this; }
	
	bool addInPort( string portName );
		// Agrega un port de entrada. Si ya existia devuelve FALSE,
		// sino devuelve TRUE.

	bool addOutPort( string portName );
		// Agrega un port de salida. Si ya existia devuelve FALSE,
		// sino devuelve TRUE.

	void getOutPorts(VirtualPortList *vpl);
		// Devuelve una lista de los puertos de salida

	const Real &value() const
		{ return this->neighbors->get(); }

	static const string cellClassName;
	static const string outPort ;

protected:
	friend class CoupledCell ;   // value
	friend class MainSimulator ; // neighborhood( NeighborhoodValue * )

	AtomicCell( const string & = cellClassName, const LocalTransAdmin::Function &id = LocalTransAdmin::InvalidFn ) ; 

	Model &initFunction() ;
	
	virtual Model &outputFunction( const InternalMessage & );

	const LocalTransAdmin::Function &localFunction() const
		{ return localFn; }
	
	void setPortInFunction( const string portName, const string functionName );

	void setPortValue( const string portName, const Real portValue );

	const NeighborhoodValue &neighborhood() const
		{ return *neighbors; }

	NeighborhoodValue &neighborhood()
		{ return *neighbors; }

	const Port &outputPort() const		// Puerto OUT
		{ return out; }

	const Port &neighborPort() const	// Puerto NEIGHBORCHANGE
		{ return neighborChange; }

	PortList	&inputPort()		// Lista de puertos IN (Dinamica)
		{ return in; }
		
	PortInFunction	&inputPortFunction()
		{ return inFunction; }
	
	PortValues	&inputPortValues()
		{ return inValues; }

	PortList	&outPortList()		// Lista de Puertos OUT
		{ return output; }		// (Dinamica)

	AtomicCell &value( const Real &val )
		{ neighbors->set(val); return *this; }

	AtomicCell &neighborhood( NeighborhoodValue * ) ;

	static const string neighborChangePort ;

private:
	NeighborhoodValue *neighbors ;
	LocalTransAdmin::Function localFn ;

	Port &out ;
	Port &neighborChange ;

	PortList 	in;		// record the In Ports (Dynamic)
	PortInFunction	inFunction;	// record the function to use when a message come from an In Port
	PortValues	inValues;	// record the last value that arrives in each port

	PortList 	output;		// record the Out Ports (Dynamic)
} ; // AtomicCell

#endif // __ATOMIC_CELL_H
