#ifndef __PINGPONG_H_
#define __PINGPONG_H_

#include <map>
#include <iostream>
#include <vector>
#include "ariba/utility/types.h"
#include "ariba/utility/system/Timer.h"
#include "ariba/utility/misc/Helper.h"
#include "ariba/utility/messages.h"
#include "ariba/utility/measurement/PathloadMeasurement.h"
#include "ariba/utility/configuration/Configuration.h"
#include "ariba/utility/logging/Logging.h"
#include "ariba/utility/measurement/PathloadMeasurement.h"
#include "ariba/utility/system/StartupInterface.h"
#include "ariba/interface/UnderlayAbstraction.h"
#include "ariba/interface/AribaContext.h"
#include "ariba/interface/ServiceInterface.h"
#include "PingPongMessage.h"

using std::vector;
using std::map;
using std::cout;
using ariba::application::pingpong::PingPongMessage;
using ariba::interface::ServiceInterface;
using ariba::interface::UnderlayAbstraction;
using ariba::interface::AribaContext;
using ariba::utility::NodeID;
using ariba::utility::LinkID;
using ariba::utility::StartupInterface;
using ariba::utility::Timer;
using ariba::utility::Configuration;
using ariba::utility::NodeID;
using ariba::utility::Identifier;
using ariba::utility::ServiceID;
using ariba::utility::PathloadMeasurement;
using ariba::utility::PathloadMeasurementListener;

namespace ariba {
namespace appplication {
namespace pingpong {

/**
/* The PingPong main class
/* This class implements an example service for demonstration purposes
/* The pingpong class sends and receives messages between two SpoVNet
/* instances
**/
class PingPong :
	public ServiceInterface,
	public StartupInterface,
	public Timer,
	public PathloadMeasurementListener {

	use_logging_h(PingPong);

public:
	PingPong();
	virtual ~PingPong();
	void setMode( bool startingNode );


	virtual void onOverlayCreate( const SpoVNetID& id );
	virtual void onOverlayDestroy( const SpoVNetID& id );
	virtual bool isJoinAllowed( const NodeID& nodeid, const SpoVNetID& spovnetid );
	virtual void onNodeJoin( const NodeID& nodeid, const SpoVNetID& spovnetid );
	virtual void onNodeLeave( const NodeID& id, const SpoVNetID& spovnetid );
	virtual void onJoinSuccess( const SpoVNetID& spovnetid );
	virtual void onJoinFail( const SpoVNetID& spovnetid );
	virtual void onLinkUp( const LinkID& link, const NodeID& local, const NodeID& remote );
	virtual void onLinkDown( const LinkID& link, const NodeID& local, const NodeID& remote );
	virtual void onLinkChanged( const LinkID& link, const NodeID& local, const NodeID& remote );
	virtual void onLinkFail(const LinkID& id, const NodeID& local, const NodeID& remote);
	virtual void onLinkQoSChanged(const LinkID& id, const NodeID& local, const NodeID& remote , const QoSParameterSet& qos);

	virtual bool receiveMessage( const Message* message, const LinkID& link, const NodeID& node );

protected:
	virtual void startup();
	virtual void shutdown();

	virtual void eventFunction(); // timer event function
	virtual void onMeasurement(NodeID node, double mbps); // measurement event function

private:
	bool startping;
	UnderlayAbstraction* abstraction;
	AribaContext* context;
	BaseOverlay* overlay;
	static ServiceID PINGPONG_ID;
	unsigned long pingid;
	typedef map<NodeID, LinkID> RemoteNodes;
	RemoteNodes remoteNodes;
};

ARIBA_SIMULATION_SERVICE(PingPong);

}}} // namespace ariba, appplication, pingpong

#endif // __PINGPONG_H_
