#include "StdAfx.h"
#include "SATDevices.h"
#include "SATExecutor.h"

bool CSATDevices::s_bEnableAndroid = true;
ULONGLONG CSATDevices::s_ulEraseDuration = 30000;
ThreadSection CSATDevices::s_ThreadSection;
std::vector<SATDEV::STDevice> CSATDevices::s_vtDevices;

void Split(vector<std::string>& vtLine, std::string strLines, const std::string strSplit)
{
	if (strLines.size() == 0 || strSplit.size() == 0)
		return;

	int nIndex = 0;
	vtLine.clear();
	std::string strtmp;
	while (std::string::npos != (nIndex = strLines.find(strSplit))) {
		strtmp = strLines.substr(0, nIndex);
		if (strtmp.size())vtLine.push_back(strtmp);
		strLines = strLines.substr(nIndex + strSplit.size());
	}

	if (strLines.size())
		vtLine.push_back(strLines);
}

std::string ExecuteCMD(std::string cmd)
{
	SECURITY_ATTRIBUTES sa = {0};
	HANDLE hRead = NULL, hWrite = NULL;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	// 创建管道;
	if ( !CreatePipe(&hRead, &hWrite, &sa, 1024) )
	{
		return "";
	}

	STARTUPINFO si = {0};
	PROCESS_INFORMATION pi = {0};
	si.cb = sizeof(STARTUPINFO);
	GetStartupInfo(&si);

	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	// 创建子进程;
	TCHAR szCommand[MAX_PATH] = {0};
	_tcscpy_s(szCommand,cmd.c_str());
	if ( !CreateProcess(NULL, szCommand, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi) )
	{
		CloseHandle(hRead);
		CloseHandle(hWrite);
	}

	// 等待进程结束;
	WaitForSingleObject(pi.hProcess, INFINITE);

	// 释放所有句柄;
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	CloseHandle(hWrite);

	// 等待缓冲写入;
	Sleep(200);
	// 读取内容;
	DWORD dwBytesRead;
	TCHAR szBuffer[1024] = {0};
	ReadFile(hRead, szBuffer, 1024, &dwBytesRead, NULL);
	CloseHandle(hRead);

	// 返回结果;
	return std::string(szBuffer);
}

CSATDevices::CSATDevices(void)
{
	m_hEvent = NULL;
	m_hWorkThread = NULL;

	// 添加一个虚拟设备;
	AddVirtualDevices("192.168.1.999:5555");
}

CSATDevices::~CSATDevices(void)
{
	EndofWork();
}

void CSATDevices::StartWork()
{
	m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( m_hEvent == NULL ) {
		return;
	}

	m_hWorkThread = CreateThread(NULL, 0, WorkThread, this, 0, NULL);
	if ( m_hWorkThread == NULL) {
		SetEvent(m_hEvent);
		CloseHandle(m_hEvent);
		CloseHandle(m_hWorkThread);
		m_hEvent = NULL;
		m_hWorkThread = NULL;
		return;
	}
}

void CSATDevices::EndofWork()
{
	// 设置事件有信号;
	if ( m_hEvent )
		SetEvent(m_hEvent);

	// 等待线程结束;
	if ( m_hWorkThread ) {
		WaitForSingleObject(m_hWorkThread, INFINITE);
		CloseHandle(m_hWorkThread);
		m_hWorkThread = NULL;
	}

	// 关闭事件句柄;
	if ( m_hEvent ) {
		CloseHandle(m_hEvent);
		m_hEvent = NULL;
	}
}

DWORD CSATDevices::WorkThread(LPVOID lpVoid)
{
	CSATDevices *that = (CSATDevices*)lpVoid;
	do 
	{
		if ( !s_bEnableAndroid )
			continue;

		// 刷新当前设备列表;
		std::vector<SATDEV::STDevice> vtDevices;
#ifdef _DEBUG
		printf("GetCurrentDevices\n");
#endif
		// 获取当前设备列表;
		GetCurrentDevices(vtDevices);

		// 遍历设备列表是否有下线设备;
		std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
		for ( ;it != s_vtDevices.end(); ) {
			if ( it->nType == SATDEV::Virtual ) {
				it++;
				continue;
			}

			if ( IsDevicesOffline(*it, vtDevices) ) {
#ifdef _DEBUG
				printf("IsDevicesOffline\n");
#endif
				if ( GetTickCount64() - it->ulOfflineTime > GLOBAL::g_stSATConfig.dwAdbTimeout ) {
					// 移除设备(需要线程加锁);
					it = s_vtDevices.erase(it);
				} else {
					if ( it->nType == SATDEV::Reticle ) {
						if ( it->nStatus == SATDEV::Offline ) {
							// offline只能reconnect才能重连;
							std::string str = "adb reconnect ";
							str.append(it->strName);
							WinExec(str.c_str(), SW_HIDE);
						} 
						else if ( it->nStatus == SATDEV::Dropline ) {
							std::string str = "adb connect ";
							str.append(it->strName);
							WinExec(str.c_str(), SW_HIDE);
						}
					} else if ( it->nType == SATDEV::Usb ) {
						// 如果是usb的话,可能要kill-server,再全部重连接;
						WinExec("adb kill-server", SW_HIDE);
						// 重连所有;
						ReConnectAllDevices();
					}

					it++;
				}
			}
			else
				it++;
		}
	} while (WaitForSingleObject(that->m_hEvent, 2500) == WAIT_TIMEOUT);

	printf("end thread\n");
	return 0;
}

void CSATDevices::DelDevices(std::string name)
{
	std::string str;
	AutoThreadSection ats(&s_ThreadSection);
	std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
	for(; it != s_vtDevices.end(); it++ ) {
		if ( _tcscmp(it->strName.c_str(), name.c_str()) == 0 ) {
			// usb设备没办法删除,此处忽略;
			if ( it->nType != SATDEV::Usb) {
				// 只有网络设备才能删除;
				str = "adb disconnect ";
				str.append(name);
				WinExec(str.c_str(), SW_HIDE);
				s_vtDevices.erase(it);
				CSATExecutor::GetInstance()->AddDevices(*it);
			}
			break;
		}
	}
}

void CSATDevices::AddReticleDevices(std::string ip)
{
	SATDEV::STDevice stDevice;
	stDevice.nType = SATDEV::Reticle;
	stDevice.strName = ip;
	stDevice.ulOfflineTime = 0;
	stDevice.nStatus = SATDEV::Online;
	stDevice.nUsageState = SATDEV::Idle;

	AutoThreadSection ats(&s_ThreadSection);
	if (!IsDeviceExist(stDevice)) {
		s_vtDevices.push_back(stDevice);
		CSATExecutor::GetInstance()->AddDevices(stDevice);
	}
}

void CSATDevices::AddVirtualDevices(std::string name)
{
	SATDEV::STDevice stDevice;
	stDevice.nType = SATDEV::Virtual;
	stDevice.strName = name;
	stDevice.ulOfflineTime = 0;
	stDevice.nStatus = SATDEV::Online;
	stDevice.nUsageState = SATDEV::Idle;

	AutoThreadSection ats(&s_ThreadSection);
	if (!IsDeviceExist(stDevice)) {
		s_vtDevices.push_back(stDevice);
		CSATExecutor::GetInstance()->AddDevices(stDevice);
	}
}

bool CSATDevices::IsDeviceExist(SATDEV::STDevice &stDevice)
{
	bool bExist = false;
	std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
	for(; it != s_vtDevices.end(); it++ ) {
		if ( _tcscmp(it->strName.c_str(), stDevice.strName.c_str()) == 0 ) {
			bExist = true;
			break;
		}
	}

	return bExist;
}

bool CSATDevices::IsDevicesOffline(SATDEV::STDevice &stDevice, std::vector<SATDEV::STDevice> &vtDevices )
{
	bool bOffline = true;
	// 在当前设备列表查询;
	std::vector<SATDEV::STDevice>::iterator it = vtDevices.begin();
	for(; it != vtDevices.end(); it++ ) {
		if ( _tcscmp(it->strName.c_str(), stDevice.strName.c_str()) == 0 ) {
			// 同步状态;
			stDevice.nStatus = it->nStatus;
			// 设备是否offline或dropline;
			if ( it->nStatus != SATDEV::Offline && it->nStatus != SATDEV::Dropline)
				bOffline = false;
			break;
		}
	}

	if ( bOffline ) {
		if ( stDevice.ulOfflineTime == 0 ) {
			// 首次检测到离线;
			if ( stDevice.nStatus != SATDEV::Offline )
				stDevice.nStatus = SATDEV::Dropline;
			stDevice.ulOfflineTime = GetTickCount64();
		}
	} else {
		// 若重新连接,重置离线时间;
		if ( stDevice.ulOfflineTime ) {
			stDevice.nStatus = SATDEV::Online;
			stDevice.ulOfflineTime = 0;
		}
	}	

	return bOffline;
}

bool CSATDevices::IsNewDevices(SATDEV::STDevice &stDevice)
{
	bool bNewDevices = true;
	std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
	for(; it != s_vtDevices.end(); it++ ) {
		if ( _tcscmp(it->strName.c_str(), stDevice.strName.c_str()) == 0 ) {
			bNewDevices = false;
			break;
		}
	}

	// 如果是新设备(一般是usb连接)
	if ( bNewDevices ) {
		AutoThreadSection ats(&s_ThreadSection);
		s_vtDevices.push_back(stDevice);
		CSATExecutor::GetInstance()->AddDevices(stDevice);
	}

	return bNewDevices;
}

void CSATDevices::GetCurrentDevices(std::vector<SATDEV::STDevice> &vtDevices)
{
	std::string strLines = ExecuteCMD("adb devices");
	std::vector<std::string> vtLine;
	Split(vtLine, strLines, "\r\n");
	int npos = -1;
	// offline设备也要加入,不区分usb或reticle;
	for ( std::vector<std::string>::iterator it = vtLine.begin(); it != vtLine.end(); it++ ) {
		//if ( _tcsicmp("List of devices attached ", it->c_str()) == 0 )
		if ( it->find("List of devices attached") != std::string::npos )
			continue;
		SATDEV::STDevice stDevice;
		// 设备类型;
		if ( it->find(":5555") != std::string::npos )
			stDevice.nType = SATDEV::Reticle;
		else if ( it->find(":5555") == std::string::npos )
			stDevice.nType = SATDEV::Reticle;
		stDevice.ulOfflineTime = 0;
		// 设备状态;
		if ( (npos = it->find("	device")) != std::string::npos )
			stDevice.nStatus = SATDEV::Online;
		else if ( (npos = it->find("	offline")) != std::string::npos )
			stDevice.nStatus = SATDEV::Offline;
		// 获取设备名;
		stDevice.strName = it->substr(0, npos);
		// 新设备否（一般用于usb设备）
		IsNewDevices(stDevice);
		// 压入容器保存;
		vtDevices.push_back(stDevice);
	}
}

void CSATDevices::ReConnectAllDevices()
{
	std::string str;
	std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
	for ( ;it != s_vtDevices.end(); it++ ) {
		if ( it->nType == SATDEV::Reticle ) {
			str = "adb connect ";
			str.append(it->strName);
			WinExec(str.c_str(), SW_HIDE);
		}
	}
}

void CSATDevices::SetDeviceUsageStatus(std::string strDevName, SATDEV::DEVICE_USAGE_STATUS status)
{
	AutoThreadSection ats(&s_ThreadSection);
	std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
	for ( ;it != s_vtDevices.end(); it++ ) {
		if ( _tcsicmp(it->strName.c_str(), strDevName.c_str() ) == 0) {
			it->nUsageState = status;
			break;
		}
	}
}

int CSATDevices::AttachDeviceName2Buffer(SATPROTO::Device (&pbuff)[30])
{
	int count = 0;
	if ( pbuff ) {
		std::string str;
		std::vector<SATDEV::STDevice>::iterator it = s_vtDevices.begin();
		for ( ;it != s_vtDevices.end(); it++ ) {
			pbuff[count].nType = it->nType;
			pbuff[count].nStatus = it->nStatus;
			memcpy_s(pbuff[count++].szName, MAX_PATH, it->strName.c_str(), it->strName.size());
			// 超过30退出;
			if ( count == 30)
				break;
		}
	}

	return count;
}