#include <rtt/os/main.h>
#include <rtt/Toolkit.hpp>
#include <rtt/TaskContexts.hpp>
#include <rtt/SequentialActivity.hpp>

using namespace RTT;

bool rw_updated = false;
bool w_updated = false;

class Reporter : public TaskContext {
public:
	Reporter(TaskContext* comp) : TaskContext("Reporter") {
		// Report RW port	
		PortInterface* rwporti = comp->ports()->getPort("rw_port");
		assert(rwporti);
		log(Debug) << "Connecting to port 'rw_port'..." << Logger::endl;
		PortInterface* rwport = rwporti->antiClone();
		assert(rwport);
		log(Debug) << "Cloned port " << rwport->getName() << Logger::endl;
		assert(rwport->connectTo(rwporti));
		log(Debug) << "Adding data update callback..." << Logger::endl;
		Handle rwh = rwporti->getNewDataOnPortEvent()->connect(boost::bind(&Reporter::dataOnPort, this, _1),
			this->engine()->events());
		assert(rwh);
		updated_ports.reserve(updated_ports.capacity() + 1);
		// Report W port	
		PortInterface* wporti = comp->ports()->getPort("w_port");
		assert(wporti);
		log(Debug) << "Connecting to port 'w_port'..." << Logger::endl;
		PortInterface* wport = wporti->antiClone();
		assert(wport);
		log(Debug) << "Cloned port " << wport->getName() << Logger::endl;
		assert(wport->connectTo(wporti));
		log(Debug) << "Adding data update callback..." << Logger::endl;
		Handle wh = wporti->getNewDataOnPortEvent()->connect(boost::bind(&Reporter::dataOnPort, this, _1),
			this->engine()->events());
		assert(wh);
		updated_ports.reserve(updated_ports.capacity() + 1);
	}
	virtual void updateHook(std::vector<RTT::PortInterface*> const &updated_ports) {
		for (std::vector<RTT::PortInterface*>::const_iterator i = updated_ports.begin();
			i != updated_ports.end(); i++)
		{
			log(Debug) << "Port " << (*i)->getName() << " updated!" << Logger::endl;
			rw_updated = ((*i)->getName() == "rw_port");
			w_updated = ((*i)->getName() == "w_port");
		}
	}
};

int ORO_main(int argc, char** argv) {
	log().setLogLevel(RTT::Logger::Debug);
	srand(time(NULL));
	int N = rand() % 100;
	int M = rand() % 100;
	std::cout << "-- N: " << N << " ; M: " << M << std::endl;
		
	// Create component
	log(Debug) << "Creating Test component..." << Logger::endl;
	TaskContext* comp = new TaskContext("Component");
	WriteDataPort<int> w_port("w_port");
	DataPort<int> rw_port("rw_port");
	comp->ports()->addPort(&rw_port);
	comp->ports()->addPort(&w_port);
	
	// Create reporter
	log(Debug) << "Creating Reporter..." << Logger::endl;
	Reporter rep(comp);
	rep.setActivity(new SequentialActivity());
	assert(rep.start());
	
	// Putting data in RW port
	log(Debug) << "Putting " << N << " in 'rw_port'" << Logger::endl;
	rw_port.Set(N);
	assert(rw_updated);
	// Putting data in W port
	log(Debug) << "Putting " << M << " in 'w_port'" << Logger::endl;
	w_port.Set(M);
	assert(w_updated);
	
	return 0;
}
