    /**
 * ll-wz.h 
 */

#ifndef ns_ll_WZ_h
#define ns_ll_WZ_h

#include <ll.h>
#include <list>

using namespace std;

struct PacketInfo
{
	int m_iSeqno;
	double m_dSendTime;
	double m_dAckTime;
    int m_iNumOfRtm;
    int m_iNumOfDupAcks;

	PacketInfo(int _iSeqno, double _dSendTime) : m_iSeqno(_iSeqno), m_dSendTime(_dSendTime)
    {
        m_dAckTime = -1;        //time ACL received.
        m_iNumOfRtm = 0;        //number of retransmissions.
        m_iNumOfDupAcks = 0;    //number of dup-acks.
    }
};

class LLWzACTimerHandler;

class LLWz : public LL {	
	friend class LLWzACTimerHandler;
public:
	LLWz();
	~LLWz();

	virtual void recv(Packet* p, Handler* h);
    
protected:
    double  m_dLastRTT;  //wan not used!!  records the last RTT value.
    int enableAckControl_;  //enable the ack control

    list<PacketInfo> m_lstWiredDataPkt;  //list container for character elements
    Packet* m_pktSampleWirelessAck; //sample wireless ack packet used to generate other acks.
    PacketInfo* m_piNextWiredDataToSend; //the pointer to the packet info of the next wired data packet to send.
    int m_iLastWirelessAck; //last ack number from  wireless end.
    double m_iLastWirelessRcvTime;  //last ack recieved time.
    double m_iWirelessAckRcvAvg;
    int m_iLastAckSent; //last ack number send back to sender.
    double m_dLastAckSentTime;
    LLWzACTimerHandler* m_acTimer;    //ack control timer used to schedule ack to be sent back to sender.
	Event* m_actmPending_;	//pending timeouts
	float m_fWiredDataRate;	//pending timeouts

	double  m_dSrtt;		/* smoothed rtt estimate */
	double  m_dRttvar;	/* linear deviation */
	double  m_dG;		/* gain in EWMA for srtt_ and rttvar_ */
private:
	void recordPacket(int iSeqno);
    int receiveWirelessAck(Packet* p);
    PacketInfo* getAckedPktSendTime(int iAck);
    double clearDataBuf(int iAck);
    bool updateNextWiredDataToSend(PacketInfo* pNextAck = NULL);
    void calcRtt(double dSendTime);
    /**
    * Construct and transmit a ack packet to sender with ack of iAckToTransmit.
    */
    void sendNextAck();
	double nextAckTime();  //returns the time to send next ack.
        void updateWiredDataRate(int iSeqno, double dRecvTime);    
};

class LLWzACTimerHandler : public Handler {
public:
    LLWzACTimerHandler() : m_llwz(NULL) {}
	LLWzACTimerHandler(LLWz *_wz) : m_llwz(_wz) {}

    void handle(Event *event);
    
protected:
    LLWz *m_llwz;   //the LLWz object which has this timer.
};

#endif
