#include "StdAfx.h"
#include "DownloadManagerImpl.h"
#include <boost/make_shared.hpp>

#define BUFFER_STEP_SIZE 1024
#define	MSG_COMPLETE_FILE	WM_USER + 100
#define MSG_COMPLETE_BUFFER	WM_USER + 101
#define MSG_ERROR			WM_USER + 102


DownloadManagerImpl::~DownloadManagerImpl(void)
{
}

void DownloadManagerImpl::init(HWND hWnd)
{
	m_hParent = hWnd;
	mspTaskManager = UEFactory::getTaskManager(emProtocol_Http);
	mspTaskManager->initTaskManager();
}

void DownloadManagerImpl::uninit( void )
{
	mspTaskManager->uninitTaskManager();
	mspTaskManager.reset();

	m_hParent = NULL;
}

TaskID DownloadManagerImpl::CreateTask( TaskInitData* pInit )
{
	if (!mspTaskManager)
	{
		return NULL;
	}

	nsURLEngine::IUETaskPtr spNewTask = mspTaskManager->getNewTask();
	TaskID taskID = reinterpret_cast<TaskID>(spNewTask.get());
	TaskDataPtr spTaskData = boost::make_shared<TaskData>(); 

	spNewTask->setCallback(static_cast<IUETaskCallback*>(this));
	spNewTask->setURL(pInit->strRequestURL.c_str());
	spNewTask->setMethod(pInit->hm == HM_POST ? emMethod_Post : emMethod_Get);
	spNewTask->setParam(pInit->strParam.c_str());

	//TaskInitData::ParamList::iterator itParam = pInit->lsParams.begin();
	//while (itParam != pInit->lsParams.end())
	//{
	//	spNewTask->addParam(itParam->first.c_str(),itParam->second.c_str());
	//	itParam++;
	//}

	if (!pInit->strFilename.empty())
	{
		spNewTask->setLocalFile(pInit->strFilename.c_str());
		spTaskData->strFile = pInit->strFilename;
	}
	else
	{
		spTaskData->vecData.reserve(BUFFER_STEP_SIZE);
	}

	spTaskData->spTask = spNewTask;

	TaskDataMap::iterator it = mmTasks.find(taskID);

	if (it != mmTasks.end())
	{
		mmTasks.erase(it);
	}

	mmTasks.insert(std::make_pair(taskID,spTaskData));

	return taskID;
}

bool DownloadManagerImpl::StartTask( TaskID taskID )
{
	TaskDataMap::iterator it = mmTasks.find(taskID);

	if (it != mmTasks.end())
	{
		mspTaskManager->startTask(it->second->spTask);

		return true;
	}

	return false;
}

void* DownloadManagerImpl::AllocCompleteBuffer( TaskID taskID )
{
	TaskDataMap::iterator it = mmTasks.find(taskID);

	if (it == mmTasks.end())
	{
		return NULL;
	}

	DownloadData* pData = new DownloadData();

	if (it->second->strFile.empty())
	{
		pData->nLen = it->second->vecData.size();
		pData->ptr = new char[pData->nLen];
		memcpy(pData->ptr,&(it->second->vecData[0]),pData->nLen);
	}
	else
	{
		pData->nLen = it->second->strFile.size() + 1;
		pData->ptr = new char[pData->nLen];
		memcpy(pData->ptr,it->second->strFile.c_str(),pData->nLen);
	}

	return reinterpret_cast<void*>(pData);
}

void DownloadManagerImpl::OnTaskProgress( double fNow,double fTotal,UETaskID taskid )
{

}

void DownloadManagerImpl::OnTaskEvent( emTaskEvent event,emEngineErrCode errCode,UETaskID taskid )
{
	if (event == emEvent_Complete)
	{
		TaskDataMap::iterator it = mmTasks.find(taskid);
		if (it != mmTasks.end())
		{
			try{
				ParamConstructor* pConstructor = static_cast<ParamConstructor*>(this);
				DownloadData* pData = NULL;
				pConstructor->ParamAlloc(it->second->strFile.empty() ? MSG_COMPLETE_BUFFER : MSG_COMPLETE_FILE,0,&taskid,reinterpret_cast<void**>(&pData));

				PostMessage(m_hParent, it->second->strFile.empty() ? MSG_COMPLETE_BUFFER : MSG_COMPLETE_FILE,
					(WPARAM)taskid, (LPARAM)pData);
/*				eventMgr->postEvent(
					EVENT_DOWNLOADMANAGER_COMPLETE,
					it->second->strFile.empty() ? DOWNLOADCOMPLETE_BUFFER : DOWNLOADCOMPLETE_FILE,
					taskid,
					pData,
					pConstructor
					);*/	
			}
			catch(...)
			{
				PostMessage(m_hParent, MSG_ERROR, (WPARAM)&taskid, NULL);
				//eventMgr->postEvent(EVENT_DOWNLOADMANAGER_ERROR,0,taskid,NULL);
			}
		}

		mmTasks.erase(taskid);
	}
	else if (event == emEvent_Error)
	{
		//eventMgr->postEvent(EVENT_DOWNLOADMANAGER_ERROR,0,taskid,NULL);
		mmTasks.erase(taskid);
	}
}

void DownloadManagerImpl::OnTaskData( UEVoidPtr ptr,unsigned int nLen,UETaskID taskid )
{
	TaskDataMap::iterator it = mmTasks.find(taskid);

	if (it != mmTasks.end())
	{
		if (it->second->strFile.empty())
		{
			std::vector<unsigned char>::size_type nSize = it->second->vecData.size();
			std::vector<unsigned char>::size_type nCaps = it->second->vecData.capacity();
			if (nSize + nLen > nCaps)
			{
				it->second->vecData.reserve(nSize + nLen + BUFFER_STEP_SIZE);
			}

			it->second->vecData.resize(nSize + nLen);
			memcpy(&(it->second->vecData[nSize]),ptr,nLen);
		}
	}
}

bool DownloadManagerImpl::StopTask( TaskID taskID )
{
	TaskDataMap::iterator it = mmTasks.find(taskID);

	if (it != mmTasks.end())
	{
		if (it->second->spTask)
		{
			it->second->spTask->cancel();
			return true;
		}
	}	

	return false;
}

void DownloadManagerImpl::ParamAlloc( unsigned int nEvent, unsigned int nSubEvent, void** param1, void** param2 )
{
	switch (nEvent)
	{
	//case EVENT_DOWNLOADMANAGER_PROGRESS:
	//	*param2 = reinterpret_cast<void*>(new DownloadProgress());
	//	break;
	case MSG_COMPLETE_BUFFER:
		*param2 = AllocCompleteBuffer(*param1);
		break;
	case MSG_COMPLETE_FILE:
		*param2 = AllocCompleteBuffer(*param1);
		break;
	}
}

void DownloadManagerImpl::ParamFree( unsigned int nEvent, unsigned int nSubEvent, void* param1, void* param2 )
{
	switch (nEvent)
	{
	//case EVENT_DOWNLOADMANAGER_PROGRESS:
	//	if (param2)
	//	{
	//		delete param2;
	//	}	
	//	break;
	case MSG_COMPLETE_BUFFER || MSG_COMPLETE_FILE:
		{
			DownloadData* pData = reinterpret_cast<DownloadData*>(param2);
			if (pData)
			{
				if (pData->ptr)
				{
					delete []pData;
				}

				delete pData;
			}
		}
		break;
	}
}

DownloadManagerImpl::DownloadManagerImpl( void )
{

}
