#include "StdAfx.h"
#include "SDK.h"
#include "CritSection.h"
#include "Global.h"
#include "DataImpl.h"
#include <sys/stat.h>

ThreadSection g_csTask;
std::list<STMid> CSDK::m_vtMidTask;

CSDK::CSDK(void):
m_hDownloadEvent(NULL),
m_hThreadDownload(NULL),
m_hReportEvent(NULL),
m_hThreadReport(NULL)
{
	Global::Init();
	Global::GetMacAddress();
}

CSDK::~CSDK(void)
{
	EndDowloadThread();
	EndReportThread();
}

int CSDK::QueryMidInfo(std::string order)
{
	if ( order.size() == 0 )
		return -1;

	CDataImpl db;
	if ( !db.Open() )
		return -2;

	STMid mid;
	int nRow = db.QueryMidInfo(order.c_str(), mid);
	if ( nRow == -1)
		return -3;

	if ( nRow == 0 )
		return 0;

	if ( nRow == 1)
	{
		if ( _tcsicmp(mid.status.c_str(), "0") == 0 )
			return 1;
		else if ( _tcsicmp(mid.status.c_str(), "1") == 0 )
			return 2;
		else if ( _tcsicmp(mid.status.c_str(), "1") == -1 )
			return 3;
	}

	return -4;
}

int CSDK::DownloadMidData(std::string order)
{
	if ( m_hThreadDownload == NULL )
	{
		m_hDownloadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		if ( m_hDownloadEvent == NULL )
		{
			return -1;
		}

		m_hThreadDownload = CreateThread(NULL, 0, ThreadDownload, this, 0, NULL);
		if ( m_hThreadDownload == NULL )
		{
			CloseHandle(m_hDownloadEvent);
			m_hDownloadEvent = NULL;
			return -1;
		}
	}

	int nRet = 0;
	STMid host_mid;
	STMid local_mid;
	// https请求;
	nRet = GetMidInfo(order, host_mid);
	if ( nRet == -1)
		return -5;
	else if ( nRet != 0 ) 
		return 0;

	// 判断该订单是否存在;
	CDataImpl db;
	if ( !db.Open() )
		return -2;

	// 查询mid;
	nRet = db.QueryMidInfo(order, local_mid);
	if ( nRet == -1)
		return -3;

	if ( nRet == 0 )
	{
		// 新增mid;
		db.InsertMidInfo(host_mid);
	}
	else if ( nRet == 1 )
	{
		// 是否已下载过,已下载过的不允许重新下载;
		if ( local_mid.status == "1" && local_mid.finish_date.size() )
			return 2;

		// 更新Mid;
		db.UpdateMidInfo(host_mid);
	}
	else if ( nRet > 1 )
		return -4;
	
	// 加入任务中;
	CSDK::AddDownloadTask(host_mid);

	return 1;
}

int CSDK::QueryKeyInfo(std::string sn, STKeys &keys)
{
	if ( sn.size() == 0 )
		return -1;

	CDataImpl db;
	if ( !db.Open() )
		return -2;

	int nRow = db.QueryKeyInfo(sn.c_str(), keys);
	if ( nRow == -1)
		return -3;

	if ( nRow == 0 )
		return 0;

	if ( nRow == 1 )
		return 1;

	return -4;
}

int CSDK::UpdateKeyCopyStatus(std::string sn )
{
	if ( sn.size() == 0 )
		return -1;

	CDataImpl db;
	if ( !db.Open() )
		return -2;

	BOOL bRet = FALSE;
	// 只更新抄写成功的状态;
	bRet = db.UpdateKeyCopyStatus(sn.c_str());	
	
	return bRet == TRUE ? 1 : 0;
}

int CSDK::UpdateKeyReportStatus(std::string sn)
{
	if ( sn.size() == 0 )
		return -1;

	CDataImpl db;
	if ( !db.Open() )
		return -2;

	BOOL bRet = FALSE;
	// 更新抄写成功状态：1，失败-1;
	bRet = db.UpdateKeyReportStatus(sn.c_str());
	
	return bRet == TRUE ? 1 : 0;
}

int CSDK::ReportKeyCopyResults(std::string sn /* = "" */)
{
	return 0;
}

void CSDK::AddDownloadTask(STMid &mid)
{
	AutoThreadSection ats(&g_csTask);
	bool has = false;
	std::list<STMid>::iterator it = m_vtMidTask.begin();
	for (; it != m_vtMidTask.end(); it++ )
	{
		if ( _tcsicmp(it->order.c_str(), mid.order.c_str()) == 0 )
		{
			has = true;
			*it = mid; // 更新;
			break;
		}
	}

	if ( !has )
	{
		m_vtMidTask.push_back(mid);
	}
}

BOOL CSDK::PopDownloadTask(STMid &mid)
{
	AutoThreadSection ats(&g_csTask);
	if ( m_vtMidTask.size() )
	{
		mid = m_vtMidTask.front();
		m_vtMidTask.pop_front();
		return TRUE;
	}

	return FALSE;
}

bool CSDK::CheckDownload(std::string file, STMid& mid)
{
	// 校验文件md5值;
	std::string fileMd5 = GetFileMD5(file.c_str());
	if ( _tcsicmp(fileMd5.c_str(), mid.pmd5.c_str()) == 0 )
	{
		// 文件下载成功,批量插入数据库;
		std::vector<STKeys> vtKeys;
		ParserKey(file, vtKeys, mid);
		if ( vtKeys.size() )
		{
			CDataImpl db;
			if ( db.Open() )
			{
				if ( db.BatchInsertKeyInfo(vtKeys) == 0 )
				{
					// 更新任务状态;
					if ( ReportDownloadStatus(mid.order) == 0 )
					{
						db.UpdateDownloadStatus(mid.order, 1);
					}

					return true;
				}
			}
		}
	}

	return false;
}

int CSDK::GetMidInfo(std::string order, STMid &mid)
{
	// http获取mid;
	std::string result;
	std::string url = "http://test.admin.ota.qhmoka.com/IDManage/getofflinelist.do?";
	std::string content = "orderNumber=";
	content.append(order);
	//content.append("&mac=");
	//content.append(Global::g_strMacs);
	CCurlClient curl;
	curl.Initialize();
	if ( curl.Posts(url, content, result) == CURLE_OK)
	{
		// 解析json字符串;
		cJSON *pJson = cJSON_Parse(result.c_str());
		if ( !pJson )
		{
			return -2;
		}

		std::string code, des;
		code = cJSON_GetObjectItem(pJson, _T("code")) ? cJSON_GetObjectItem(pJson, _T("code"))->valuestring : "";
		des = cJSON_GetObjectItem(pJson, _T("des")) ? cJSON_GetObjectItem(pJson, _T("des"))->valuestring : "";
		cJSON *pData = cJSON_GetObjectItem(pJson, _T("data"));
		if ( _tcsicmp(code.c_str(), "1000") )
		{
			cJSON_Delete(pJson);
			return -3;
		}
		
		if ( !pData )
		{
			cJSON_Delete(pJson);
			return -4;
		}

		TCHAR szData[10] = {0};
		mid.order = cJSON_GetObjectItem(pData, _T("order_number")) ? cJSON_GetObjectItem(pData, _T("order_number"))->valuestring : "";
		mid.version = cJSON_GetObjectItem(pData, _T("soft_version")) ? cJSON_GetObjectItem(pData, _T("soft_version"))->valuestring : "";
		//mid.number = cJSON_GetObjectItem(pData, _T("order_quantity")) ? cJSON_GetObjectItem(pData, _T("order_quantity"))->valuestring : "";
		_itoa_s(cJSON_GetObjectItem(pData, _T("order_quantity")) ? cJSON_GetObjectItem(pData, _T("order_quantity"))->valueint : 0, szData, 10);
		mid.number = szData;
		mid.pmd5 = cJSON_GetObjectItem(pData, _T("packet_md5")) ? cJSON_GetObjectItem(pData, _T("packet_md5"))->valuestring : "";
		mid.ctype = cJSON_GetObjectItem(pData, _T("client_type")) ? cJSON_GetObjectItem(pData, _T("client_type"))->valuestring : "";
		mid.pid = cJSON_GetObjectItem(pData, _T("project_id")) ? cJSON_GetObjectItem(pData, _T("project_id"))->valuestring : "";
		mid.purl = cJSON_GetObjectItem(pData, _T("packet_url")) ? cJSON_GetObjectItem(pData, _T("packet_url"))->valuestring : "";
		//mid.psize = cJSON_GetObjectItem(pData, _T("packet_size")) ? cJSON_GetObjectItem(pData, _T("packet_size"))->valuestring : "";
		memset(szData, 0, 10);
		_itoa_s(cJSON_GetObjectItem(pData, _T("packet_size")) ? cJSON_GetObjectItem(pData, _T("packet_size"))->valueint : 0, szData, 10);
		mid.psize = szData;

		cJSON_Delete(pJson);
		pJson = NULL;

		return 0;
	}

	// http请求异常;
	return -1;
}

int CSDK::ReportDownloadStatus(std::string order)
{
	// http获取mid;
	std::string result;
	std::string url = "http://test.admin.ota.qhmoka.com/IDManage/getreportofflinesn.do?";
	std::string content = "orderNumber=";
	content.append(order);

	CCurlClient curl;
	curl.Initialize();
	if ( curl.Posts(url, content, result) == CURLE_OK)
	{
		// 解析json字符串;
		cJSON *pJson = cJSON_Parse(result.c_str());
		if ( !pJson )
		{
			return -2;
		}

		std::string code, des;
		code = cJSON_GetObjectItem(pJson, _T("code")) ? cJSON_GetObjectItem(pJson, _T("code"))->valuestring : "";
		des = cJSON_GetObjectItem(pJson, _T("des")) ? cJSON_GetObjectItem(pJson, _T("des"))->valuestring : "";

		if ( _tcsicmp(code.c_str(), "1000") && _tcsicmp(code.c_str(), "1006"))
		{
			cJSON_Delete(pJson);
			return -3;
		}

		cJSON_Delete(pJson);
		pJson = NULL;

		return 0;
	}

	// http请求异常;
	return -1;
}

void CSDK::ParserKey(std::string file, std::vector<STKeys> &vtKyes, STMid &mid)
{
	// 读取文件;
	FILE* pf = NULL;
	_tfopen_s(&pf, file.c_str(), _T("rb"));
	if (!pf)
		return;
	// 获取文件长度;
	fseek(pf, 0, SEEK_END);
	size_t file_size = ftell(pf);
	fseek(pf, 0, SEEK_SET);
	// 读取文件内容;
	byte* pdata = (byte*)malloc(file_size);
	fread(pdata, file_size, 1, pf);
	fclose(pf);

	// Json数据;
	cJSON* pJson = cJSON_Parse((const char*)pdata);
	if (pJson == NULL)
	{
		goto end;
	}

	//////////////////////////////////////////////////////////////////////////
	// 解析Json;
	cJSON *pItem = NULL;
	int nCount = cJSON_GetArraySize(pJson);
	for ( int i = 0; i < nCount; i++ )
	{
		pItem = cJSON_GetArrayItem(pJson, i);
		if ( pItem )
		{
			STKeys key;
			key.bid = mid.order;
			key.pid = mid.pid;
			// 序列号;
			key.sn = cJSON_GetObjectItem(pItem, _T("sn")) ? cJSON_GetObjectItem(pItem, _T("sn"))->valuestring : "";
			cJSON *pJsonKeys = cJSON_GetObjectItem(pItem, _T("key"));
			if ( pJsonKeys )
			{
				char *lpszKeys = cJSON_Print(pJsonKeys);
				if ( lpszKeys)
				{
					key.keys = lpszKeys;
					free(lpszKeys);
				}
			}
			vtKyes.push_back(key);
		}
	}

end:
	if (pdata)
		free(pdata);

	if (pJson)
		cJSON_Delete(pJson);
}

bool CSDK::ParserSNKey(std::string json, SNKeys &snKey)
{
	bool bRet = false;
	// Json数据;
	cJSON* pJson = cJSON_Parse(json.c_str());
	if ( pJson )
	{
		// 序列号;
		snKey.did = cJSON_GetObjectItem(pJson, _T("sn")) ? cJSON_GetObjectItem(pJson, _T("sn"))->valuestring : "";
		snKey.mac = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.hdcp = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.hdcp22 = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.widi = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.widevine = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.esn = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";
		snKey.cikey = cJSON_GetObjectItem(pJson, _T("keys")) ? cJSON_GetObjectItem(pJson, _T("keys"))->valuestring : "";

		bRet = true;
	}

	if (pJson)
		cJSON_Delete(pJson);

	return bRet;
}

DWORD CSDK::ThreadDownload(LPVOID lpParam)
{
	CSDK *that = (CSDK*)lpParam;
	// key包文件路径;
	TCHAR szKeyPacket[MAX_PATH] = {0};
	do 
	{
		if ( m_vtMidTask.size() )
		{
			// 取出任务;
			STMid mid = m_vtMidTask.front();

			// 判断文件是否存在，并检验md5值;
			_stprintf_s(szKeyPacket, _T("%scache\\%s.json"), Global::g_szCurModuleDir, mid.order.c_str());
 			if ( _taccess(szKeyPacket, 0) != -1 )
			{
				if ( CheckDownload(szKeyPacket, mid) )
				{
					// 弹出任务;
					AutoThreadSection ats(&g_csTask);
					if ( m_vtMidTask.size() )
					{
						m_vtMidTask.pop_front();
					}

					continue;
				}

				// 文件大小相同,删除文件;
				struct stat fst;
				if ( stat(szKeyPacket, &fst) == 0 )
				{
					if ( atoi(mid.psize.c_str()) == fst.st_size )
						DeleteFile(szKeyPacket);
				}
			}

			// 文件不存在,开始下载;
			CCurlClient curl;
			curl.Initialize();
			curl.DownloadEx(mid.purl, szKeyPacket);
		}
	} while (WaitForSingleObject(that->m_hDownloadEvent, 5000) == WAIT_TIMEOUT );

	return 0L;
}

void CSDK::EndDowloadThread()
{
	if ( m_hDownloadEvent )
	{
		SetEvent(m_hDownloadEvent);
	}

	if ( m_hThreadDownload)
	{
		WaitForSingleObject(m_hThreadDownload, INFINITE);
		CloseHandle(m_hThreadDownload);
		m_hThreadDownload = NULL;

		if ( m_hDownloadEvent )
			CloseHandle(m_hDownloadEvent);
		m_hDownloadEvent = NULL;
	}		 
}

DWORD CSDK::ThreadReport(LPVOID lpParam)
{
	CSDK *that = (CSDK*)lpParam;
	do 
	{
		// 自动上报;

	} while (WaitForSingleObject(that->m_hReportEvent, 3000) == WAIT_TIMEOUT );

	return 0L;
}

void CSDK::EndReportThread()
{
	if ( m_hReportEvent )
	{
		SetEvent(m_hReportEvent);
	}

	if ( m_hThreadReport)
	{
		WaitForSingleObject(m_hThreadReport, INFINITE);
		CloseHandle(m_hThreadReport);
		m_hThreadReport = NULL;

		if ( m_hReportEvent )
			CloseHandle(m_hReportEvent);
		m_hReportEvent = NULL;
	}		 
}