#include "UIProbeLink.h"
#include "UITerminal.h"
#include "Network.h"
#include "BufferedNode.h"
#include <sstream>

namespace FD
{
	using namespace std;

	class UIProbeLinkNode;
	DECLARE_NODE(UIProbeLinkNode);

	//WE HAVE CHOSEN A BUFFERED NODE TO AVOID
	//NOTIFYING EVERY TIME GETOUTPUT IS CALLED.
	//IS IT THE RIGHT CHOICE ?
	class UIProbeLinkNode : public BufferedNode
	{
		protected:
		int m_inputID;
		int m_outputID;

		std::vector<UIObserverIF*> m_observers;	

		public:

		void registerIF(UIObserverIF* client)
		{
			if (client)
			{
				m_observers.push_back(client);
			}
		}

		UIProbeLinkNode(std::string nodeName, ParameterSet params)
   			: BufferedNode(nodeName, params)
		{
			m_inputID = addInput("INPUT");
			m_outputID = addOutput("OUTPUT");
		}

		void calculate(int output_id, int count, Buffer &out)
   		{
			//GET INPUT
      			ObjectRef ReturnValue = getInput(m_inputID, count);
			
			//NOTIFY OBSERVERS
			for (unsigned int i = 0; i < m_observers.size(); i++)
			{
				//CLONING THE OBJET IS SAFER, BUT WILL THROW AN EXCEPTION
				//IF NOT IMPLEMENTED.
				try 
				{
					std::cerr<<"UIProbeLinkNode::calculate -- will notify"<<std::endl;
					m_observers[i]->notify(ReturnValue->clone());
					std::cerr<<"UIProbeLinkNode::calculate --notify complete"<<std::endl;
				}
				catch(BaseException *e)
				{
					e->print(std::cerr);
					delete e;
					try 
					{
						m_observers[i]->notify(ReturnValue);

						std::cerr<<"UIProbeLinkNode::calculate --notify complete"<<std::endl;
					}
					catch (BaseException *e)
					{						
						e->print(std::cerr);
						throw e->add(new GeneralException("Not working properly",__FILE__,__LINE__));
					}
				}
			}

			//INPUT = OUTPUT
      			out[count] = ReturnValue;
  		 }


	}; 


	UIProbeLink::UIProbeLink(UITerminal *_from, UITerminal *_to, const char *points_str)
	 : UILink(_from, _to, points_str)
	{
		//SOMETHING TO DO ?
	}


	UIProbeLink::~UIProbeLink()
	{
		//SOMETHING TO DO ?
	}
	
	void UIProbeLink::saveXML(xmlNode *root)
	{
		xmlNodePtr tree;
		if (m_points.size()<=2)
		{
			tree = xmlNewChild(root, NULL, (xmlChar *)"ProbeLink", NULL);

		}
		else 
		{
			stringstream str;
			list<GUILinkPoint*>::iterator it = m_points.begin();
			while(it != m_points.end())
			{
				str << (*it)->x << " " << (*it)->y << " ";
				it++;
			}
			tree = xmlNewChild(root, NULL, (xmlChar *)"ProbeLink", (xmlChar*)str.str().c_str());
		}
		
		xmlSetProp(tree, (xmlChar *)"from", (xmlChar *)from->getNode()->getName().c_str());
		xmlSetProp(tree, (xmlChar *)"output", (xmlChar *)from->getName().c_str());
		xmlSetProp(tree, (xmlChar *)"to", (xmlChar *)to->getNode()->getName().c_str());
		xmlSetProp(tree, (xmlChar *)"input", (xmlChar *)to->getName().c_str());

	}

   	void UIProbeLink::build(Network *net)
	{
		static int probenumber = 0;

		//THIS WILL CREATE A "DUMMY" NODE THAT IS CONNECTED TO 
		//ON BOTH SIDES (INPUT-OUTPUT) TO REAL PROCESSING NODES
		//THE "PROBE" NODE WILL CALL NOTIFY IN ITS GETOUTPUT FUNCTION
		//TO NOTIFY ALL OBSERVERS...
		stringstream nodename;
	
		nodename << "UIProbeLink_"<<probenumber++;
	
		//CREATE NODE
		UIProbeLinkNode* probeNode = new UIProbeLinkNode(nodename.str(),ParameterSet());

		//ADD NODE TO NETWORK
		net->addNode(*probeNode);
		

		//COPY REGISTERED LISTENER(S)
		for (unsigned int i = 0; i < m_observers.size(); i++)
		{
			probeNode->registerIF(m_observers[i]);
		}
		

		//CONNECT NODES PROPERLY
		if (!to || !from)
		throw new GeneralException("Link is not connected at both endes", __FILE__, __LINE__);
		if (!to->getNode() || !from->getNode())
		throw new GeneralException("Cannot find node associated with link", __FILE__, __LINE__);

		//ADD PROBE IN THE MIDDLE OF STANDARD NODES!!!
		net->connect(to->getNode()->getName(), to->getName(), 
			"OUTPUT", nodename.str());		

		net->connect(nodename.str(), "INPUT", 
			from->getNode()->getName(), from->getName());
		
	
	}	


	void UIProbeLink::registerIF(UIObserverIF* client)
	{
		if (client)
		{
			m_observers.push_back(client);
		}
	}

} //namespace FD





syntax highlighted by Code2HTML, v. 0.9.1