#ifndef _IMODULE_H_
#define _IMODULE_H_

#include "../tobject.h"
#include "../ptr.h"

#include "varinst.h"
#include "vardef.h"
#include "messageclass.h"

#include <string>
#include <map>
#include <iostream>

using namespace std;

class ModuleType;
class ModuleManager;
class MessageClass;
class VarInst;

/**
 * \brief Represent "algorithm instance" in the modular system.
 *
 * Handles message receiving, store variables and provides methods to access them.
 * 
 * \date 01-29-2006
 *
 * \author Onrej Svejdar.
 *
 * \todo 
 *
 * \bug 
 *
 */
class IModule:public TObject
{
	typedef map<string,Ptr<VarInst> > t_vars;
	string name;
	ModuleManager* manager;
	ModuleType* parent;
	t_vars vars;

	// register module under given module type
	void registerModule(ModuleType* parent,const string& name);
public:
	static Ptr<IModule> nullRef;
	static const char* type;
	const char* getType() const;

	inline const string& getName() const
	{
		return name;
	}
	IModule():manager(0),parent(0) {}
	
	/**
	 * \brief runs module
	 */
	virtual void run()=0;
	
	/**
	 * \brief handle messages receiving
	 * \param mesg pointer to object representing message
	 */
	virtual void receiveMessage(TObject* mesg) {}
	
	/**
	 * \brief called by ModuleType class after instantiation, for graphic setup etc.
	 */
	virtual void afterInstantiate() {}

	/**
	 * \brief print variables into stream
	 * \param o output stream
	 */
	void printVariables(ostream& o) const;
	
	/**
	 * \brief test on module name (text comparsion)
	 * \param s another's module name
	 * \return true on match
	 */
	inline bool operator==(const string& s) const
	{
		return getName()==s;
	}
	
	// return variable by name

	/**
	 * \brief Return variable instance named varName. If no such instance exists, returns NULL.
	 * \param varName name of variable instance
	 * \return variable instance
	 */
	inline VarInst* getVariable(const string& varName)
	{
		if (vars.find(varName)==vars.end()) return 0;
		return vars[varName];
	}
	
	/**
	 * \brief Same as function getVariable() via operator.
	 * \param varName name of variable instance
	 * \return variable instance.
	 */
	inline VarInst* operator[](const string& varName)
	{
		return vars[varName];
	}

	/**
	 * \brief returns pointer to module manager
	 * \return module manager
	 */
	ModuleManager* getManager()
	{
		return manager;
	}

	/**
	 * \brief returns pointer to module type
	 * \return module type
	 */
	ModuleType* getModuleType()
	{
		return parent;
	}

	friend class ModuleType;
};

#endif/*_IMODULE_H_*/
