 // VCDemoDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "VCDemo.h"
#include "VCDemoDlg.h"
#include "LoginDlg.h"
#include "ModulePath.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

uintptr_t g_hThread;
unsigned __stdcall OnInitDevList(void* pParam)
{
	CVCDemoDlg *pMainDlg = (CVCDemoDlg *)pParam;
	
	int ret=0;
	do 
	{
		ret = FC_InitMataDataInf();
		if(ret)
		{			
			Sleep(10);
		}
	} while (ret);
		
	ret = 0;
	do 
	{		
		ret = FC_RefreshHeadendDeviceList();
		if (ret)
		{			
			Sleep(50);
			continue;
		}		
	} while (ret == -1);	
	
	if (pMainDlg)
	{
		//更新设备列表信息		
		pMainDlg->OnUpdataDevInfoTree();		
	}

	_endthreadex(0);
	return 0;
}

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)	
END_MESSAGE_MAP()


// CVCDemoDlg 对话框




CVCDemoDlg::CVCDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVCDemoDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_bPlay =FALSE;
}

void CVCDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_DEV_TREE, m_treeDev);
}

BEGIN_MESSAGE_MAP(CVCDemoDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BTN_LOGIN, &CVCDemoDlg::OnBnClickedBtnLogin)
	ON_BN_CLICKED(IDC_BTN_GET_DEVLIST, &CVCDemoDlg::OnBnClickedBtnGetDevlist)
	ON_BN_CLICKED(IDC_BTN_STOP_VIDEO, &CVCDemoDlg::OnBnClickedBtnStopVideo)
	ON_WM_CLOSE()
	ON_NOTIFY(NM_DBLCLK, IDC_DEV_TREE, &CVCDemoDlg::OnNMDblclkDevTree)
	ON_MESSAGE( WM_USR_MSGGUI, OnMainGuiMsgProc )
END_MESSAGE_MAP()


// CVCDemoDlg 消息处理程序

BOOL CVCDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	S8 logfilename[1024];
	strcpy(logfilename,::GetModuleFileDirectory().c_str());
	sprintf(logfilename,"%s\\%s",logfilename,LOGFILENAME);
	mlogInit(logfilename);

	FC_Init(this->m_hWnd);

	m_ImageList.Create(IDB_TREE_IMAGE, 16, 1, RGB(255, 0, 255));
	m_treeDev.SetItemHeight(20);
	m_treeDev.SetImageList(&m_ImageList, TVSIL_NORMAL);

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CVCDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CVCDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标显示。
//
HCURSOR CVCDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CVCDemoDlg::OnBnClickedBtnLogin()
{
	// TODO: 登录服务器
	CLoginDlg oLoginDlg;
	if(oLoginDlg.DoModal() == IDOK)
	{
		GetDlgItem(IDC_BTN_LOGIN)->EnableWindow(FALSE);		
		AfxMessageBox("登录成功!");
		//获取设备列表
		OnBnClickedBtnGetDevlist();
		
	}
		
	return;
}

void CVCDemoDlg::OnBnClickedBtnGetDevlist()
{
	// TODO: 获取设备列表
	m_HRootDev = m_treeDev.InsertItem("设备获取中,请稍后...", 0, 0, TVI_ROOT, TVI_LAST);
	g_hThread = _beginthreadex(0,0,OnInitDevList, this, 0, 0);
	GetDlgItem(IDC_BTN_GET_DEVLIST)->EnableWindow(FALSE);
}

void CVCDemoDlg::OnBnClickedBtnStopVideo()
{
	// TODO:停止播放
	if (m_dspwndinfo.bVideo)
	{
		int ret = FC_RemoveWatch(GetDlgItem(IDC_VIDEO_AREA)->m_hWnd);		
		m_dspwndinfo.bVideo = false;
		m_bPlay = FALSE;
		m_pCameraDev = NULL;		
		GetDlgItem(IDC_VIDEO_AREA)->Invalidate(TRUE);		
	}
}

void CVCDemoDlg::OnUpdataDevInfoTree()
{
	if (FC_GetRelatedDeviceList().size()==0)
		return;

	int nNewSlaveCount=0;
	int nOldSlaveCount=0;
	std::list<CMasterDevice *>::iterator  iterMaster;
	std::list<CDeviceBaseInfo *>::iterator  iterSlave;
	for (iterMaster = FC_GetRelatedDeviceList().begin(); iterMaster != FC_GetRelatedDeviceList().end(); iterMaster++)
	{
		m_lstRelatedDevice.push_back((*iterMaster));
	}

	RefreshDevTree(&m_treeDev);
}

HTREEITEM CVCDemoDlg::CheckGroup(CTreeCtrl *pTree, CString szGroup)
{	
	HTREEITEM  HRootDev = pTree->GetRootItem();	
	pTree->Expand(HRootDev, TVE_EXPAND);
	HTREEITEM  HItem = pTree->GetChildItem(HRootDev);
	do 
	{				
		CString  strText = pTree->GetItemText(HItem);
		if (strText.CompareNoCase(szGroup) == 0)
		{
			return HItem;
		}
		HItem = pTree->GetNextItem(HItem, TVGN_NEXT);
	} while (HItem);

	return  NULL;
}

int CVCDemoDlg::RefreshDevTree(CTreeCtrl *pTree)
{
	if(pTree == NULL)
		return 0;

	pTree->DeleteAllItems();

	std::list<CMasterDevice *>::iterator  iterMaster;
	std::list<CDeviceBaseInfo *>::iterator  iterSlave;

	HTREEITEM  HRootDev;
	HTREEITEM  HItemDev;
	HTREEITEM  HChildDev;	

	HRootDev = pTree->InsertItem("设备列表", 0, 0, TVI_ROOT, TVI_LAST);
	if(m_lstRelatedDevice.size() == 0)
		return 0;

	for(iterMaster = m_lstRelatedDevice.begin(); iterMaster != m_lstRelatedDevice.end(); iterMaster++)
	{
		BOOL  bSetGroup = FALSE;
		if ((*iterMaster)->oMasterBaseInfo.szDevGroupID[0] != '\0')
		{
			bSetGroup = TRUE;
			CString strMsg;
			strMsg.Format("%s(%s)", (*iterMaster)->szDevGroupName, (*iterMaster)->szDomainName);
			HTREEITEM HGroupItem = CheckGroup(pTree, strMsg);			
			if (HGroupItem == NULL)
			{				
				HItemDev = pTree->InsertItem(strMsg, 1, 1, HRootDev, TVI_LAST);
			}
			else
				HItemDev = HGroupItem;
		}		

		for(iterSlave = (*iterMaster)->m_lstDevice.begin(); iterSlave != (*iterMaster)->m_lstDevice.end(); iterSlave++)
		{						
			if (bSetGroup)
			{
				if ((*iterMaster)->oMasterBaseInfo.nState == 2)
					HChildDev = pTree->InsertItem((*iterSlave)->szDevName, 3, 3, HItemDev, TVI_LAST);
				else
					HChildDev = pTree->InsertItem((*iterSlave)->szDevName, 2, 2, HItemDev, TVI_LAST);				

			}
			else
			{
				if ((*iterMaster)->oMasterBaseInfo.nState == 2)
					HChildDev = pTree->InsertItem((*iterSlave)->szDevName, 3, 3, HRootDev, TVI_LAST);
				else
					HChildDev = pTree->InsertItem((*iterSlave)->szDevName, 2, 2, HRootDev, TVI_LAST);				

			}

			pTree->SetItemData(HChildDev, (DWORD)(*iterSlave));			
		}		
	}

	pTree->Expand(HRootDev, TVE_EXPAND);
	HTREEITEM  HItem = pTree->GetChildItem(HRootDev);
	do 
	{		
		pTree->Expand(HItem, TVE_EXPAND);
		HItem = pTree->GetNextItem(HItem, TVGN_NEXT);
	} while (HItem);

	pTree->SendMessage(WM_VSCROLL, SB_TOP);

	return 0;
}

void CVCDemoDlg::OnClose()
{
	// TODO: 退出程序
	OnBnClickedBtnStopVideo();
	WaitForSingleObject(reinterpret_cast<HANDLE>(g_hThread),INFINITE); //一直等到线程结束
	CloseHandle(reinterpret_cast<HANDLE>(g_hThread));

	FC_ClientLogOut();
	FC_Free();

	CDialog::OnClose();
}

void CVCDemoDlg::OnNMDblclkDevTree(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 双击设备列表进行播放
	CPoint   pt;   
	GetCursorPos(&pt);   
	m_treeDev.ScreenToClient(&pt);
	HTREEITEM   hTreeItemSelected   =   m_treeDev.HitTest(pt);
	m_treeDev.Select(hTreeItemSelected, TVGN_DROPHILITE );
	HTREEITEM   hRootItem = m_treeDev.GetRootItem();

	if ((hTreeItemSelected != NULL) && (!m_treeDev.ItemHasChildren(hTreeItemSelected)) && (m_treeDev.GetParentItem(hTreeItemSelected)!=hRootItem)) 
	{
		//set device info
		CCameraDevice *pCameraDev = (CCameraDevice*)m_treeDev.GetItemData(hTreeItemSelected);
		if(pCameraDev == NULL)
			return;

		if (m_dspwndinfo.bVideo)
		{
			OnBnClickedBtnStopVideo();
		}

		int ret = FC_addWatch(0, GetDlgItem(IDC_VIDEO_AREA)->m_hWnd, pCameraDev, 1);
		if(!ret)
		{		
			GetDlgItem(IDC_VIDEO_AREA)->SetWindowText("请求视频流,请稍后!");	
			m_pCameraDev = pCameraDev;
			m_dspwndinfo.bVideo = true;
		}
	}

	*pResult = 0;
}

LRESULT CVCDemoDlg::OnMainGuiMsgProc( WPARAM wParam, LPARAM lParam )
{
	switch(wParam) {
		case RECVDATATIMEOUT:	
			GetDlgItem(IDC_VIDEO_AREA)->SetWindowText("接收视频流超时,重新请求！");		
			return 0;
		case FIRSTPLAY:		
			GetDlgItem(IDC_VIDEO_AREA)->SetWindowText("");
			m_bPlay = TRUE;		
			return 0;
		case RECORDEND:		
			if(m_dspwndinfo.bLocRecord)
			{
				//停止录像
				FC_StopLocalRecord(GetDlgItem(IDC_VIDEO_AREA)->m_hWnd);			
				m_dspwndinfo.bLocRecord = FALSE;
			}
			return 0;
	case VS_MSG_INVALIDATE_WND:		
		return 0;		
	case VS_VIDEO_MSG_INVITE:
		On_InviteMsgProc((MSG_Invite_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_IPC_STATUS_NOTIFY:
		On_IPCStatusNotifyMsgProc((MSG_IPCStatus_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_ALL_IPC_STATUS_NOTIFY:
		On_AllIPCStatusNotifyMsgProc();
		return 0;
	case VS_ALL_CAM_REGINFO_NOTIFY:
		//On_AllCamRegInfoNotifyMsgProc();
		return 0;
	case VS_CONFIG_CHANGE_NOTIFY:
		//On_ConfigChangeNotifyMsgProc();
		return 0;
	case VS_MSG_RECORD_STATUS:
		//On_RecordStatusNotifyMsgProc((MSG_Record_t*)lParam);		
		free((void*)lParam);
		return 0;
	case VS_PTZ_MSG_REQPRIVI:
		//
		return 0;		
	case VS_PTZ_MSG_ACT:
		//On_PTZActMsgProc((MSG_PTZ_ACT_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_MSG_TACKBACK:
		//On_TackBackMsgProc((MSG_Takeback_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_MSG_ALARM:
		//On_AlarmMsgProc((MSG_Alarm_t*)lParam);
		free((void*)lParam);		
		return 0;
	case VS_MSG_EVENT:
		//On_EventMsgProc((MSG_Event_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_MSG_REC_FILE:
		//On_RecFileMsgProc((MSG_RecordFile_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_MSG_REC_DISTRIBUTE_FILE:
		//On_RecDistributeFileMsgProc((MSG_RecDistrition_t*)lParam);
		free((void*)lParam);
		return 0;
	case VS_AUDIO_MSG_REQPRIVI:
		//
		return 0;
	case VS_AUDIO_BC_MSG_REQPRIVI:
		//
		return 0;
	case VS_AUDIO_REQ_AGAIN:
		//
		return 0;
	case VS_AUDIO_MSG_CLOSE:
		//				
		return 0;
	case VS_SET_PSW_RSP:
		//
		return 0;
	case VS_DOWNLOAD_REC_FILE:
		//On_DownloadRecFileMsgProc((MSG_DownloadFile_t *)lParam);
		free((void*)lParam);
		return 0;
	case VS_DOWNLOAD_SPECIFIC_REC_FILE:
		//On_DownloadSpecificRecFileMsgProc((MSG_DownloadFile_t *)lParam);
		free((void*)lParam);
		return 0;
	case VS_RSP_DOWNLOAD_DVR_FILE:
		//
		return 0;
	case VS_NOTIFY_PROGRESS_DVR_FILE:
		//
		return 0;
	case VS_NOTIFY_UPLOAD_FAILED:
		//
		return 0;
	default:
		return 0;
	}

	return S_OK;
}

void CVCDemoDlg::On_InviteMsgProc(MSG_Invite_t *pInviteMsg)
{
	if ( pInviteMsg->result)
	{
		GetDlgItem(IDC_VIDEO_AREA)->SetWindowText("视频流请求失败!");
	}
	else
	{
		GetDlgItem(IDC_VIDEO_AREA)->SetWindowText("视频流请求成功,等待视频流...");
	}	
}

void CVCDemoDlg::On_IPCStatusNotifyMsgProc(MSG_IPCStatus_t *pIPCStatusMsg)
{
	RefreshDevTree(&m_treeDev, pIPCStatusMsg->szDevId, pIPCStatusMsg->nState, 0);
}

int CVCDemoDlg::RefreshDevTree(CTreeCtrl *pTree, S8* pDevId, U32 nStatus, U32 nType)
{
	if(pTree == NULL)
		return 0;

	HTREEITEM  HRootDev = pTree->GetRootItem();	
	pTree->Expand(HRootDev, TVE_EXPAND);
	HTREEITEM  HItem = pTree->GetChildItem(HRootDev);
	HTREEITEM  HChildDev = NULL;
	do 
	{
		while(pTree->ItemHasChildren(HItem))
		{
			HChildDev = pTree->GetChildItem(HItem);
			HItem = HChildDev;
		}
		HChildDev = HItem;	
		if(HChildDev==NULL)
			return 0;

		CCameraDevice *pCameraDev = (CCameraDevice*)pTree->GetItemData(HChildDev);		
		if (pCameraDev)			
		{			
			if (nType==0)//IPC status change
			{
				if(strcmp(pDevId, pCameraDev->getMaster()->oMasterBaseInfo.szDevId) == 0)
				{
					if (nStatus == 2 && (pCameraDev->nRecStatus == 1))//online and recording status
						pTree->SetItemImage(HChildDev, 6, 6);
					if (nStatus == 2 && (pCameraDev->nRecStatus != 1))//online and no recording status
						pTree->SetItemImage(HChildDev, 3, 3);
					if (nStatus != 2 && (pCameraDev->nRecStatus == 1))//offline and recording status
						pTree->SetItemImage(HChildDev, 4, 4);
					if (nStatus != 2 && (pCameraDev->nRecStatus != 1))//offline and no recording status
						pTree->SetItemImage(HChildDev,2, 2);

					pCameraDev->getMaster()->oMasterBaseInfo.nState = nStatus;
					pTree->SetItemData(HChildDev, (DWORD)(pCameraDev));
					break;
				}

			}
			else//camera record status change
			{
				if(strcmp(pDevId, pCameraDev->szDevId) == 0)
				{
					if (pCameraDev->getMaster()->oMasterBaseInfo.nState == 2 && (nStatus == 1))//online and recording status
						pTree->SetItemImage(HChildDev, 6, 6);
					if (pCameraDev->getMaster()->oMasterBaseInfo.nState == 2 && (nStatus != 1))//online and no recording status
						pTree->SetItemImage(HChildDev, 3, 3);
					if (pCameraDev->getMaster()->oMasterBaseInfo.nState != 2 && (nStatus == 1))//offline and recording status
						pTree->SetItemImage(HChildDev, 4, 4);
					if (pCameraDev->getMaster()->oMasterBaseInfo.nState != 2 && (nStatus != 1))//offline and no recording status
						pTree->SetItemImage(HChildDev, 2, 2);

					pCameraDev->nRecStatus = nStatus;
					pTree->SetItemData(HChildDev, (DWORD)(pCameraDev));
					break;
				}
			}					
		}		

		if (pTree->GetNextItem(HChildDev, TVGN_NEXT) != NULL)
		{
			HItem = pTree->GetNextItem(HChildDev, TVGN_NEXT);
		}
		else
		{
			HItem = pTree->GetParentItem(HChildDev);
			HItem = pTree->GetNextItem(HItem, TVGN_NEXT);
		}		

	} while (HItem);

	return 0;
}

void CVCDemoDlg::On_AllIPCStatusNotifyMsgProc()
{
	std::list<CMasterDevice*>::iterator  iterMaster;
	std::list<CDeviceBaseInfo*>::iterator  iterSlave;
	std::list<MSG_IPCStatus_t>::iterator  iterStatus;

	for (iterMaster = m_lstRelatedDevice.begin(); iterMaster != m_lstRelatedDevice.end(); iterMaster++)
	{
		BOOL  bFind = FALSE;
		for (iterStatus = FC_GetAllIPCStatusList().begin(); iterStatus != FC_GetAllIPCStatusList().end(); iterStatus++)
		{
			if (strcmp((*iterMaster)->szDevId, (*iterStatus).szDevId) == 0)
			{
				if((*iterMaster)->oMasterBaseInfo.nState != (*iterStatus).nState)
				{
					(*iterMaster)->oMasterBaseInfo.nState = (*iterStatus).nState;
					RefreshDevTree(&m_treeDev, (*iterMaster)->oMasterBaseInfo.szDevId,(*iterStatus).nState,0);
				}
				
				
				bFind = TRUE;
				break;
			}
		}

		if(!bFind)
		{
			if ((*iterMaster)->oMasterBaseInfo.nState != 0)
			{
				(*iterMaster)->oMasterBaseInfo.nState = 0;
				RefreshDevTree(&m_treeDev, (*iterMaster)->oMasterBaseInfo.szDevId,0,0);
			}
			
		}
	}
	
}