/**
@file interface.hpp
@brief ネットワーク用インターフェイス

*/

#ifndef DKUTIL_NETWORK_INTERFACE_HPP
#define DKUTIL_NETWORK_INTERFACE_HPP



namespace dkutil{

class ICorrespondence{
public:
	virtual ~ICorrespondence(){
	}
	///@return 今、繋いでいる状態だったらtrue
	virtual bool good()const = 0;
	///繋いでいたのを切断
	virtual void disconnect() = 0;
	
	
};

#ifdef WIN32
	
	

	
class CWinInet : public IInternet
{
public:
	typedef BOOL (*InternetSetOption_type)(
    IN HINTERNET hInternet,
    IN DWORD dwOption,
    IN LPVOID lpBuffer,
    IN DWORD dwBufferLength
	);
	typedef BOOL (*InternetQueryOption_type)(
    IN HINTERNET hInternet,
    IN DWORD dwOption,
    OUT LPVOID lpBuffer,
    IN OUT LPDWORD lpdwBufferLength
	);


	typedef DWORD (*InternetAttemptConnect_type)(
    IN DWORD dwReserved
	);
	typedef BOOL (*InternetCloseHandle_type)(
    IN HINTERNET hInet
	);
	typedef HINTERNET (*InternetOpen_type)(
    IN LPCSTR lpszAgent,
    IN DWORD dwAccessType,
    IN LPCSTR lpszProxyName,
    IN LPCSTR lpszProxyBypass,
    IN DWORD dwFlags
	);
	/**
	Internet Explorerのバージョンを得る。
	@return -1で失敗 0がIE3 それ以降IEのバージョンが上がるたびに戻り値が1づつ上がる (IE4 == 1 IE5 == 2 ... )
	*/
	static int GetIEVersion(){
		INTERNET_VERSION_INFO info;
	  DWORD dwSize;
		int r = -1;
	  dwSize = sizeof(info);
		
		DLLManager mgr("Wininet.dll");
		
		InternetQueryOption_type pf = 
			(InternetQueryOption_type)mgr.find("InternetQueryOption");

		if(NULL==pf){
			return -1;
		}
		
	  if( pf( 0, INTERNET_OPTION_VERSION, &info, &dwSize ) ){
	    if( info.dwMajorVersion == 1 ){
	    	if(info.dwMinorVersion < 0){
	    		r = -1;
	    	}else{
	    		r = info.dwMinorVersion;
	    	}
	      /*
	    	switch( info.dwMinorVersion ){
	        case 0:
	          Edit1->Text = "Internet Explorer 3";
	          break;
	        case 1:
	          Edit1->Text = "Internet Explorer 4";
	          break;
	        case 2:
	          Edit1->Text = "Internet Explorer 5";
	          break;
	        default:
	         	r = -1;
	          break;
	      }
	    	*/
	    	
	    }
	  }
		return r;
	}



private:
	///WinInetハンドル
	HINTERNET mH;
	///DLLマネージャー
	DLLManager mDLL;
	
	///エラーメッセージ
	std::string mLastError[1024];
	
	//各関数へのポインタ
	

	InternetSetOption_type InternetSetOption;
	
	InternetAttemptConnect_type InternetAttemptConnect;

	InternetOpen_type InternetOpen;
	
	InternetCloseHandle_type InternetCloseHandle;

	InternetQueryOption_type InternetQueryOption;

public:


	CWinInet(const char *dllname="Wininet.dll"){
		mH = NULL;
		if(false==mDLL.reset(dllname)){
			return;
		}

		
		InternetSetOption = 
			(InternetSetOption_type)mDLL.find("InternetSetOption");
		
		InternetAttemptConnect = 
			(InternetAttemptConnect_type)mDLL.find("InternetAttemptConnect");
		
		InternetOpen =
			(InternetOpen_type)mDLL.find("InternetOpen");
		
		InternetCloseHandle - 
			(InternetCloseHandle_type)mDLL.find("InternetCloseHandle");
		
		
	}
	virtual ~CWinInet(){
		close();
	}
		
	///インターネットに接続を確立（常時接続でない場合）
	bool attemptConnect()
	{//ERROR_SUCCESSだと成功
		return ERROR_SUCCESS==InternetAttemptConnect(0);
	}
	///タイムアウトを設定する
	bool setTimeOut(size_t TimeOut = 5000)
	{
		return TRUE==InternetSetOption( h, INTERNET_OPTION_RECEIVE_TIMEOUT, &TimeOut, sizeof(TimeOut) );
	}
	bool open(const char *userAgent,int option)
	{
		DWORD Opt;
		switch(option){
		case preconfig_type:
			Opt = INTERNET_OPEN_TYPE_PRECONFIG;
			break;
		case direct_type:
			Opt = INTERNET_OPEN_TYPE_DIRECT;
			break;
		case proxy_type:
			Opt = INTERNET_OPEN_TYPE_PROXY;
			break;
		default:
			return false;
		}
		mH = InternetOpen(userAgent,Opt,NULL,NULL,0);
		if(NULL==mH)
		{
			mLastError = GetWin32LastErrorString();
			return false;
		}
		return true;
	}
	void close(){
		if(mH){
			InternetCloseHandle( mH );
			mH = NULL;
		}
		
	}
	const char *errorStr()const{
		return mLastError.c_str();
	}

	
	
};
	
typedef CWinInet CInternet;
	
#else //posix...
	
	
#endif

}//end of dkutil namespace



#endif