#include "stdafx.h"
#include "TcpServerProcess.h"

#include "SHA1.h"
#include "ATW.h"
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

CTcpServerProcess::CTcpServerProcess():m_server(this)
{
	m_reve_event = NULL;
	m_connid_event = NULL;
}


CTcpServerProcess::~CTcpServerProcess()
{
	
}

void CTcpServerProcess::Send(CONNID dwConnID, LPCSTR msg)
{
	int iLen = (int)strlen(msg);
	m_server.Send(dwConnID,(LPBYTE)msg, iLen);
}
void CTcpServerProcess::Send(CONNID dwConnID, const BYTE* pBuffer, int iLength)
{
	m_server.Send(dwConnID, pBuffer, iLength);
}

void CTcpServerProcess::BroadMsg(json broadmsg)
{
	Sleep(800);
	DWORD count =m_server.GetConnectionCount();
	CONNID *pIDs = new CONNID[count];
	m_server.GetAllConnectionIDs(pIDs, count);

	for (unsigned int i = 0; i < count; ++i)
		Send(pIDs[i], (broadmsg.dump() + "\r\n").c_str());
	delete pIDs;
}

void CTcpServerProcess::BroadMsg(const BYTE* pBuffer, int iLength)
{
	DWORD count = m_server.GetConnectionCount();
	CONNID *pIDs = new CONNID[count];
	m_server.GetAllConnectionIDs(pIDs, count);

	for (unsigned int i = 0; i < count; ++i)
		Send(pIDs[i], pBuffer, iLength);
	delete pIDs;
}


EnHandleResult CTcpServerProcess::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
{
	TCHAR szAddress[40];
	int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
	USHORT usPort;
	pSender->GetListenAddress(szAddress, iAddressLen, usPort);
	return HR_OK;
}

EnHandleResult CTcpServerProcess::OnAccept(ITcpServer* pSender, CONNID dwConnID, SOCKET soClient)
{
	
	std::lock_guard<std::mutex> lk(m_muter_tcp);
	BOOL bPass = TRUE;
	TCHAR szAddress[40];
	int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
	USHORT usPort;

	pSender->GetRemoteAddress(dwConnID, szAddress, iAddressLen, usPort);

	//SetconnidEvent();
	/*TCP_MSG info = { 0 };
	info.dwConnID = dwConnID;
	info.tp = std::chrono::high_resolution_clock::now();
	info.ip = WChar2Ansi(AtoW(szAddress));
	m_tcpmsg.insert(pair<CONNID, TCP_MSG>(dwConnID, info));*/

	TCP_MSG *pInfo = new TCP_MSG;
	pInfo->dwConnID = dwConnID;
	pInfo->flag = 0;
	pInfo->userId = szAddress;
	pInfo->tp = std::chrono::high_resolution_clock::now();
	pInfo->ip = szAddress;

	m_userIdInfo[pInfo->ip] = dwConnID;
	pSender->SetConnectionExtra(dwConnID, pInfo);

	//m_timer.add_task([this]() {CloseConnect(); }, 0);//不需要进行心跳判断
	return bPass ? HR_OK : HR_ERROR;
}

EnHandleResult CTcpServerProcess::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{

	return HR_OK;
}
EnHandleResult CTcpServerProcess::OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
	std::lock_guard<std::mutex> lk(m_muter_tcp);
	std::string msg = "";
	for (int i = 0; i < iLength; i++)
	{
		msg += pData[i];
	}

	TCP_MSG *pInfo = nullptr;
	pSender->GetConnectionExtra(dwConnID, (PVOID *)&pInfo);
	if (pInfo)
	{
		pInfo->tp = std::chrono::high_resolution_clock::now();
		pInfo->deal_msg.push_back(msg);
	}
	m_safemsg.push(pInfo);
	SetRecvEvent();

	/*std::lock_guard<std::mutex> lk(m_muter_tcp);
	TCP_MSG rcvmsg{};
	rcvmsg.dwConnID = dwConnID;
	for (int i = 0; i < iLength; i++)
	{
	
		rcvmsg.msg += pData[i];
	}
	rcvmsg.deal_msg.push_back(rcvmsg.msg);
	auto tcpmsg = m_tcpmsg.find(dwConnID);
	if (tcpmsg != m_tcpmsg.end())
	{
		rcvmsg.flag = tcpmsg->second.flag;
		rcvmsg.type = tcpmsg->second.type;
		rcvmsg.ip = tcpmsg->second.ip;
		rcvmsg.userId = tcpmsg->second.userId;
		tcpmsg->second.tp= std::chrono::high_resolution_clock::now();
	}
	
	m_rcvmsg.push_back(rcvmsg);
	SetRecvEvent();*/
	
	return HR_OK;
}

EnHandleResult CTcpServerProcess::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
	{
		/*std::lock_guard<std::mutex> lk(m_muter_tcp);
		Iter iter = m_tcpmsg.find(dwConnID);
		if (iter != m_tcpmsg.end())
		{
			auto usr = m_userIdInfo.find(iter->second.userId);
			if (usr != m_userIdInfo.end() && usr->second== dwConnID)m_userIdInfo.erase(usr);
			m_tcpmsg.erase(iter);
		}*/

		TCP_MSG *pInfo = nullptr;
		pSender->GetConnectionExtra(dwConnID, (PVOID *)&pInfo);
		/*if (pInfo)
		{
			auto usr = m_userIdInfo.find(pInfo->userId);
			if (usr != m_userIdInfo.end() && usr->second == dwConnID)m_userIdInfo.erase(usr);
			delete pInfo;
		}*/
		if (pInfo)
		{
			pInfo->flag = -1;
			m_safemsg.push(pInfo);
		}
		
	}
	
	return HR_OK;
}

EnHandleResult CTcpServerProcess::OnShutdown(ITcpServer* pSender)
{
	return HR_OK;
}
void CTcpServerProcess::WaitRecvEvent()
{
	WaitForSingleObject(m_reve_event, INFINITE);
}
void CTcpServerProcess::SetRecvEvent()
{
	SetEvent(m_reve_event);
}
void CTcpServerProcess::WaitconnidEvent()
{
	WaitForSingleObject(m_connid_event, INFINITE);
}
void CTcpServerProcess::SetconnidEvent()
{
	SetEvent(m_connid_event);
}

bool CTcpServerProcess::GetConnid(std::string addr, CONNID &dwConnID)
{
	std::lock_guard<std::mutex> lkaddr(m_muter_addr);
	AddrIter addriter = m_tcpaddr_connid.find(addr);
	if (addriter != m_tcpaddr_connid.end())
	{
		dwConnID = addriter->second;
		return true;
	}
	return false;
}

bool CTcpServerProcess::ReadMsg(std::vector<string>& vec, CONNID &dwConnID, int &flag,std::string &ip, std::string &userId)
{
	/*if (m_rcvmsg.size() <= 0)return false;
	std::lock_guard<std::mutex> lk(m_muter_tcp);
	TCP_MSG rcvmsg = m_rcvmsg.front();
	m_rcvmsg.pop_front();
	dwConnID = rcvmsg.dwConnID;
	flag = rcvmsg.flag;
	ip = rcvmsg.ip;
	userId =rcvmsg.userId;
	if (rcvmsg.deal_msg.size() > 0)
	{
		vec.swap(rcvmsg.deal_msg);
		return true;
	}
	return false; */
	//std::lock_guard<std::mutex> lk(m_muter_tcp);
	TCP_MSG *pmsg = nullptr;
	m_safemsg.wait_and_pop(pmsg);
	if (pmsg == nullptr)return false;
	dwConnID = pmsg->dwConnID;
	flag = pmsg->flag;
	ip = pmsg->ip;
	userId = pmsg->userId;
	if (pmsg->flag == 0)
		pmsg->flag = 1;
	if (pmsg->deal_msg.size() > 0)
	{
		vec.swap(pmsg->deal_msg);
		
	}
	return true;
}

void CTcpServerProcess::CloseClient(CONNID dwConnID)
{
	m_server.CloseClient(dwConnID);
}

int CTcpServerProcess::Start()
{
	m_reve_event = CreateEvent(NULL,FALSE,FALSE,NULL);
	m_connid_event = CreateEvent(NULL, FALSE, FALSE, NULL);
	TCHAR addr[MAX_PATH];
	_stprintf_s(addr, MAX_PATH, _T("%S"), m_addr.c_str());//%S宽字符  
	if (!m_server.Start(m_addr.c_str(), m_port))
	{
		return -1;
	}
	m_timer.run();
	return 0;
}
void CTcpServerProcess::Stop()
{
	SetRecvEvent();
	m_server.Stop();
	if (m_reve_event != NULL)
		CloseHandle(m_reve_event);
	if (m_connid_event != NULL)
		CloseHandle(m_connid_event);
}

std::string CTcpServerProcess::WChar2Ansi(std::wstring wstr)
{
	int nLen = WideCharToMultiByte(CP_ACP, 0, LPCWSTR(wstr.c_str()), -1, NULL, 0, NULL, NULL);

	if (nLen <= 0) return std::string("");

	char* pszDst = new char[nLen];
	if (NULL == pszDst) return std::string("");

	WideCharToMultiByte(CP_ACP, 0, LPCWSTR(wstr.c_str()), -1, pszDst, nLen, NULL, NULL);
	pszDst[nLen - 1] = 0;

	std::string strTemp(pszDst);
	delete[] pszDst;

	return strTemp;
}

int CTcpServerProcess::GetConnectionCount()
{
	return m_server.GetConnectionCount();
}


void CTcpServerProcess::CloseConnect()
{
	static std::chrono::high_resolution_clock::time_point local_tp = std::chrono::high_resolution_clock::now();
	auto tp = std::chrono::high_resolution_clock::now();
	auto tmp = std::chrono::duration_cast<std::chrono::seconds>(tp - local_tp).count();
	if (tmp>30)
	{
		local_tp = tp;
		std::map<CONNID, TCP_MSG> _map(m_tcpmsg);
		for (auto m : _map)
		{
			tmp = std::chrono::duration_cast<std::chrono::seconds>(tp - m.second.tp).count();
			if (tmp > (15 * 60))
			{
				m_server.Disconnect(m.second.dwConnID);
			}
		}
	}
}

void CTcpServerProcess::CloseConnect(CONNID dwConnID)
{
	m_server.Disconnect(dwConnID);
}

void CTcpServerProcess::DeleteInfo(CONNID dwConnID)
{
	TCP_MSG *pInfo = nullptr;
	m_server.GetConnectionExtra(dwConnID, (PVOID *)&pInfo);
	if (pInfo)
	{
		delete pInfo;
	}
}
