#pragma once
#include <windows.h>
#include <winsock.h>
#include "types.h"

typedef struct tagIPINFO {
	u_char Ttl;				// Time To Live
	u_char Tos;				// Type Of Service
	u_char IPFlags;			// IP flags
	u_char OptSize;			// Size of options data
	u_char FAR* Options;	// Options data buffer
} IPINFO, *PIPINFO;

typedef struct tagICMPECHO {
	u_long		Source;		// Source address
	u_long		Status;		// IP status
	u_long		RTTime;		// Round trip time in milliseconds
	u_short		DataSize;	// Reply data size
	u_short		Reserved;	// Unknown
	void FAR*	pData;		// Reply data buffer
	IPINFO		ipInfo;		// Reply options
} ICMPECHO, *PICMPECHO;

class CPingThread: public CWinThread
{
	DECLARE_DYNCREATE(CPingThread)

protected:
	CPingThread(void);

public:
	~CPingThread(void);
	bool SetIP(uint16 minup, uint16 maxup, CString DynupNic);
	void StopDynup(void);
	void StartDynup(void);
	void EndDynup(void);
	void SetInitialPing(void)	{ initial_ping = Ping(); }
	int	 Ping();
	
	virtual int	 Run(); // Achieve Maximal Upload Capacity
	void		 Init();
	virtual	BOOL InitInstance() { return true; }

private:
	static const unsigned int m_ping_values = 3;
	
	int		m_wait_ms;
	DWORD	check_trigger;

	int		ping[m_ping_values];
	
	int		initial_ping;		// Inital ping just after starting emule
	double	upload;				// upload calculated next
	int		hping;				// Current timevalue of the last ping action
	int		raw_ping;
	int		normalized_ping;	// Ping normalized
	int		average_ping;		// Average ping
	int		soll_ping;

	double  maxUpload;			// maximal Dynup Upload
	double  minUpload;			// minimal Dynup Upload

	bool	isDynup;			// is Dynup enabled ?
	bool	librariesloaded;	// are the libraries loaded
	
	WSADATA			wsaData;		// WSADATA
	ICMPECHO		icmpEcho;		// ICMP Echo reply buffer
	HMODULE			hndlFile;		// Handle for IcmpCreateFile()
	HMODULE			hndlIcmp;		// LoadLibrary() handle to ICMP.DLL
    LPHOSTENT		pHost;			// Pointer to host entry structure
    struct in_addr	iaDest;			// Internet address structure
	DWORD*			dwAddress;		// IP Address
	IPINFO			ipInfo;			// IP Options structure
	int				nRet;			// General use return code
	DWORD			dwRet;			// DWORD return code
	
	// ICMP.DLL Export Function Pointers
	HMODULE	(WINAPI* pIcmpCreateFile)(VOID);
	BOOL	(WINAPI* pIcmpCloseHandle)(HMODULE);
	DWORD	(WINAPI* pIcmpSendEcho)(HMODULE, DWORD, LPVOID, WORD, PIPINFO, LPVOID, DWORD, DWORD);
	VOID	CALLBACK APCPing(ULONG_PTR dwParam);
};
