#include "StdAfx.h"
#include "HTTPSession.h"
#include "EconomicRateInfo.h"
#include "LightMutex.h"

class CHTTPSession::CImpl
{
public:
	CImpl() {}
	virtual ~CImpl() {}

	virtual bool OpenURL(const tstring& rsURL) = 0;
	virtual bool ReadResponce(tstring& rsResponce)const = 0;
};

namespace
{
// 	class CImplMS : public CHTTPSession::CImpl
// 	{
// 	public:
// 		CImplMS() 
// 			: m_hSession(::InternetOpen(_T("Dioksin"),PRE_CONFIG_INTERNET_ACCESS,NULL,INTERNET_INVALID_PORT_NUMBER,0)),
// 			m_hRequest(NULL)
// 		{
// 
// 		}
// 
// 		~CImplMS()
// 		{
// 			if(m_hRequest)
// 			{
// 				::InternetCloseHandle(m_hRequest);
// 			}
// 
// 			if(m_hSession)
// 			{
// 				::InternetCloseHandle(m_hSession);
// 			}
// 		}
// 
// 		virtual bool OpenURL(const tstring& rsURL)
// 		{
// 			if(NULL == m_hSession)
// 			{
// 				return false;
// 			}
// 
// 			if(NULL != m_hRequest)
// 			{
// 				::InternetCloseHandle(m_hRequest);
// 				m_hRequest = NULL;
// 			}
// 
// 			m_hRequest = ::InternetOpenUrl(m_hSession,rsURL.c_str(),NULL,0,INTERNET_FLAG_RELOAD,0);
// 			return NULL != m_hRequest;
// 		}
// 
// 		virtual bool ReadResponce(tstring& rsResponce)const
// 		{
// 			if(NULL == m_hRequest)
// 			{
// 				return false;
// 			}
// 
// 			std::string sBuffer;
// 			bool bResult = true;
// 			DWORD cbRead = 0;
// 			char szBuffer[1024];
// 			do{
// 				if(FALSE == ::InternetReadFile(m_hRequest,szBuffer,1024,&cbRead))
// 				{
// 					bResult = false;
// 					break;
// 				}
// 				if (0 == cbRead)
// 				{
// 					break;  // Stop.
// 				}
// 				else
// 				{
// 					sBuffer.insert(sBuffer.size(),szBuffer,cbRead);
// 				}
// 			}while(true);
// 
// 			if(true == bResult)
// 			{
// 				USES_CONVERSION;
// 				rsResponce = A2CT(sBuffer.c_str());
// 			}
// 
// 			return bResult;
// 		}
// 	private:
// 		HINTERNET m_hSession;
// 		HINTERNET m_hRequest;
// 	};
// 
	int find_header(const NETLIBHTTPREQUEST* pRequest,const char* hdr)
	{
		for(int i = 0;i < pRequest->headersCount; ++i) 
		{
			if (0 == _stricmp(pRequest->headers[i].szName,hdr)) 
			{
				return i;
			}
		}

		return -1;
	}


	class CImplMI : public CHTTPSession::CImpl
	{
	public:
		CImplMI() {}

		static bool Init()
		{
			assert(NULL == g_hNetLib);

			NETLIBUSER nlu = {0};
			nlu.cbSize = sizeof(nlu);
			nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION|NUF_TCHAR;
			nlu.szSettingsModule = QUOTES_PROTOCOL_NAME;
			nlu.ptszDescriptiveName = TranslateT("Quotes HTTP connections");
			g_hNetLib = reinterpret_cast<HANDLE>(CallService(MS_NETLIB_REGISTERUSER,0,(LPARAM)&nlu));
			return (NULL != g_hNetLib);
		}

		static bool IsValid(){return NULL != g_hNetLib;}

		virtual bool OpenURL(const tstring& rsURL)
		{
// 			USES_CONVERSION;

			m_aURL.swap(TBuffer());

			std::string s = quotes_t2a(rsURL.c_str());
			const char* psz = s.c_str();//T2CA(rsURL.c_str());
			m_aURL.insert(m_aURL.begin(),psz,psz+strlen(psz)+1);
			return true;

		}
		virtual bool ReadResponce(tstring& rsResponce)const
		{
			if(true == m_aURL.empty())
			{
				return false;
			}


			NETLIBHTTPREQUEST nlhr = {0};
			nlhr.cbSize = sizeof(nlhr);
			nlhr.requestType = REQUEST_GET;
			nlhr.flags = NLHRF_DUMPASTEXT|NLHRF_HTTP11|NLHRF_REDIRECT;
			char* pURL = &*(m_aURL.begin());
			nlhr.szUrl = pURL;

			nlhr.headersCount = 4;
			nlhr.headers=(NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount);
			nlhr.headers[0].szName   = "User-Agent";
			nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
			nlhr.headers[1].szName  = "Connection";
			nlhr.headers[1].szValue = "close";
			nlhr.headers[2].szName  = "Cache-Control";
			nlhr.headers[2].szValue = "no-cache";
			nlhr.headers[3].szName  = "Pragma";
			nlhr.headers[3].szValue = "no-cache";
			// 			nlhr.headers[4].szName  = "Accept-Encoding";
			// 			nlhr.headers[4].szValue = "deflate, gzip";
			// 			nlhr.headers[5].szName  = "Cookie";
			// 			nlhr.headers[5].szValue = cookie;

			bool bResult = false;
			NETLIBHTTPREQUEST* pReply = NULL;
			
			{
				CGuard<CLightMutex> guard(m_mx);
				pReply = reinterpret_cast<NETLIBHTTPREQUEST*>(CallService(MS_NETLIB_HTTPTRANSACTION,
					reinterpret_cast<WPARAM>(g_hNetLib),reinterpret_cast<LPARAM>(&nlhr)));
			}

			if(pReply)
			{
				if ((200 == pReply->resultCode) && (pReply->dataLength > 0)) 
				{
					TBuffer apBuffer;
					apBuffer.insert(apBuffer.begin(),pReply->pData,pReply->pData+pReply->dataLength);
					apBuffer.push_back('\0');					

					char* pResult = &*(apBuffer.begin());
					int nIndex = find_header(pReply,"Content-Type");
					if ((-1 != nIndex) && (NULL != strstr(_strlwr(pReply->headers[nIndex].szValue),"utf-8")))
					{
						TCHAR* p = mir_utf8decodeT(pResult);
						rsResponce = p;
						mir_free(p);
					}
					else
					{
// 						USES_CONVERSION;
// 						LPCTSTR p = A2CT(pResult);
						rsResponce = quotes_a2t(pResult);//p;
					}

					bResult = true;
				}

				CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,reinterpret_cast<LPARAM>(pReply));
			}

			mir_free(nlhr.headers);

			return bResult;
		}

	private:
		static HANDLE g_hNetLib;
		typedef std::vector<char> TBuffer;
		mutable TBuffer m_aURL;
		mutable CLightMutex m_mx;
	};

	HANDLE CImplMI::g_hNetLib = NULL;

// 	CHTTPSession::CImpl* create_impl()
// 	{
// 		if(true == CImplMI::IsValid())
// 		{
// 			return new CImplMI;
// 		}
// 		else
// 		{
// 			return new CImplMS;
// 		}
// 	}
}


CHTTPSession::CHTTPSession()
			 : m_pImpl(new CImplMI)
{
}

CHTTPSession::~CHTTPSession()
{
}

bool CHTTPSession::OpenURL(const tstring& rsURL)
{
	return m_pImpl->OpenURL(rsURL);
}

bool CHTTPSession::ReadResponce(tstring& rsResponce)const
{
	return m_pImpl->ReadResponce(rsResponce);
}

bool CHTTPSession::Init()
{
	return CImplMI::Init();
}