/**
 * delay.h
 */

#ifndef ns_delay_h
#define ns_delay_h

#include <assert.h>

#include "packet.h"
#include "queue.h"
#include "ip.h"
#include "connector.h"

#include <list>

using namespace std;

//packet are queued when wireless link is down.
struct QueuedPacketInfo
{
	Packet* m_pPacket;
    Handler* m_pHandler;

	QueuedPacketInfo(Packet * _p, Handler * _h)
        : m_pPacket(_p), m_pHandler(_h)
    {
    }
};

class Delay_WirelessUpTimerHandler;

class LinkDelay : public Connector {
    friend class Delay_WirelessUpTimerHandler;
    
 public:

	enum LinkDelay_DelayMode
	{
		LD_DelayMode_Constant = 0,
		LD_DelayMode_Random
	};

    LinkDelay();
    ~LinkDelay();
	void recv(Packet* p, Handler*);
	void send(Packet* p, Handler*);
	void handle(Event* e);
	double delay()
    {
        //wan
        assert(false); //it seems this is neve called.
        
        return delay_;
    }
//wan
    double getDelay(Packet* p); //my added func.  it will return the link delay with variation if appliable.
        
	inline double txtime(Packet* p) {
		return (8. * hdr_cmn::access(p)->size() / bandwidth_);
	}
	double bandwidth() const { return bandwidth_; }
	void pktintran(int src, int group);
 protected:
	int command(int argc, const char*const* argv);
	void reset();
	double bandwidth_;	/* bandwidth of underlying link (bits/sec) */
	double delay_;		/* line latency */
	Event intr_;
	int dynamic_;		/* indicates whether or not link is ~ */

	PacketQueue* itq_;
	int total_[4];

//wan
private:
	int delayMode_;

    list<QueuedPacketInfo> m_lstDelayedWiredDataPkt;  //this is used to queue the packet received when wireless link is done.
    double m_dWirelessDownTime;
    double m_dWirelessDownDuration;
	Event* m_wutmPending_;	//pending timeouts
    Delay_WirelessUpTimerHandler* m_wirelessUpTimer;
    
    bool handleWirelessLinkDown(Packet *p, Handler *h);
    void sendQueuedPacketOnWirelessLink();
};

/**
* The timer class implimented handle() method to send queued data packet to MH after wireless link is up.
*/
class Delay_WirelessUpTimerHandler : public Handler {
public:
    Delay_WirelessUpTimerHandler() : m_parent(NULL) {}
	Delay_WirelessUpTimerHandler(LinkDelay *_p) : m_parent(_p) {}

    void handle(Event *event);

protected:
    LinkDelay *m_parent;   //the LLWz object which has this timer.
};

#endif
