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

#include "stdafx.h"
#include "IntelligentDevice.h"
#include "IntelligentEventDlg.h"


#include "ShowPictureDlg.h"

#include <math.h>
#include <atlconv.h>
#include <algorithm>

#define LISTSIZE 10
#define GUIDLEN  64
#define PLAYPORT 450
struct EventPara
{
	LLONG lAnalyzerHandle;
	DWORD dwAlarmType;
	char* pAlarmInfo;
	BYTE *pBuffer;
	DWORD dwBufSize;
	int nSequence;
};


typedef struct __ALARM_ITEM
{
	std::string strGUID;
	int		nAlarmType;

}ALARM_ITEM, *LPALARM_ITEM;


// CIntelligentEventDlgDlg 对话框

IMPLEMENT_DYNAMIC(CIntelligentEventDlg, CDialog)

CIntelligentEventDlg::CIntelligentEventDlg(CWnd* pParent /*=NULL*/)
: CDialog(CIntelligentEventDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CIntelligentEventDlg)
	m_strUserName = _T("admin");
	m_strPort = _T("37777");
	m_strPasswd = _T("admin");
	//}}AFX_DATA_INIT

	m_lPlayID = 0;
	m_loginID = 0;
	m_nChannelNum = 0;

	m_nFilterEventType = EVENT_IVS_ALL;
	m_index = 0;


	InitializeCriticalSection(&m_csEventList);
	InitializeCriticalSection(&m_csLCEventInfo);
	InitializeCriticalSection(&m_csAttachList);


	m_playAPI.LoadPlayDll();
}

CIntelligentEventDlg::~CIntelligentEventDlg()
{
	DeleteCriticalSection(&m_csEventList);
	DeleteCriticalSection(&m_csLCEventInfo);
	DeleteCriticalSection(&m_csAttachList);

	DeleteAllStoreEventData();

}

void CIntelligentEventDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_EVENTINFO, m_lcEventInfo);
	DDX_Control(pDX, IDC_BTN_DETACHEVENT, m_btnDetachEvent);
	DDX_Control(pDX, IDC_BTN_ATTACHEVENT, m_btnAttachEvent);
	DDX_Control(pDX, IDC_BTN_STOPREALPLAY, m_btnStopRealPlay);
	DDX_Control(pDX, IDC_BTN_STARTREALPLAY, m_btnStartRealPlay);
	DDX_Control(pDX, IDC_CBX_CHANNEL, m_cbxChannel);
	DDX_Control(pDX, IDC_BTN_LOGOUT, m_btnLogout);
	DDX_Control(pDX, IDC_BTN_LOGIN, m_btnLogin);
	DDX_Control(pDX, IDC_IPADDRESS, m_IPCtrl);
	DDX_Text(pDX, IDC_EDIT_USERNAME, m_strUserName);
	DDX_Text(pDX, IDC_EDIT_PORT, m_strPort);
	DDX_Text(pDX, IDC_EDIT_PASSWD, m_strPasswd);
	DDX_Control(pDX, IDC_CBX_EVENT, m_cbxEvent);
	DDX_Control(pDX, IDC_STATIC_PICTURE, m_EventPic);
}


BEGIN_MESSAGE_MAP(CIntelligentEventDlg, CDialog)

	ON_BN_CLICKED(IDC_BTN_LOGIN, &CIntelligentEventDlg::OnBtnLogin)
	ON_BN_CLICKED(IDC_BTN_LOGOUT, &CIntelligentEventDlg::OnBtnLogout)
	
	ON_BN_CLICKED(IDC_BTN_STARTREALPLAY, &CIntelligentEventDlg::OnBtnStartrealplay)
	ON_BN_CLICKED(IDC_BTN_STOPREALPLAY, &CIntelligentEventDlg::OnBtnStoprealplay)
	ON_BN_CLICKED(IDC_BTN_ATTACHEVENT, &CIntelligentEventDlg::OnBtnAttachevent)
	ON_BN_CLICKED(IDC_BTN_DETACHEVENT, &CIntelligentEventDlg::OnBtnDetachevent)
	ON_CBN_SELCHANGE(IDC_CBX_CHANNEL, &CIntelligentEventDlg::OnSelchangeCbxChannel)
	ON_MESSAGE(WM_USER_ALAMR_COME, &CIntelligentEventDlg::OnAlarmCome)
	ON_MESSAGE(WM_EVENT_DISCONNECT, &CIntelligentEventDlg::OnDeviceDisConnect)
	ON_MESSAGE(WM_EVENT_RECONNECT, &CIntelligentEventDlg::OnDeviceReconnect)
	ON_CBN_SELCHANGE(IDC_CBX_EVENT, &CIntelligentEventDlg::OnCbnSelchangeCbxEvent)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST_EVENTINFO, &CIntelligentEventDlg::OnNMDblclkListEventinfo)

	ON_WM_DESTROY()
END_MESSAGE_MAP()






/////////////////////////////////////////////////////////////////////////////
// CIntelligentEventDlg message handlers

BOOL CIntelligentEventDlg::PreTranslateMessage(MSG* pMsg)
{
	// Enter key
	if(pMsg->message == WM_KEYDOWN &&
		pMsg->wParam == VK_RETURN)
	{
		return TRUE;
	}

	// Escape key
	if(pMsg->message == WM_KEYDOWN &&
		pMsg->wParam == VK_ESCAPE)
	{
		return TRUE;
	}

	return CDialog::PreTranslateMessage(pMsg);
}

void CIntelligentEventDlg::OnBtnLogin() 
{
	USES_CONVERSION;
	// TODO: Add your control notification handler code here
	BOOL bInvalid = UpdateData(TRUE);
	if ( FALSE == bInvalid)
	{
		return;
	}

	int err = 0;	//Storage the possible error return value.
	char *pchDVRIP;
	CString strDvrIP = GetDeviceIP();
	pchDVRIP = T2A(strDvrIP);
	WORD wDVRPort=(WORD)atoi(T2A(m_strPort));
	char *pchUserName=T2A(m_strUserName);
	char *pchPassword= T2A(m_strPasswd);

	//Call log in interface 
	NET_DEVICEINFO_Ex netDevInfo = {0};
	LLONG lRet = CLIENT_LoginEx2(pchDVRIP,wDVRPort,pchUserName,pchPassword,EM_LOGIN_SPEC_CAP_TCP,NULL,&netDevInfo,&err);
	if(0 != lRet)
	{
		m_loginID = lRet;
		m_nChannelNum = netDevInfo.nChanNum;

		/*update control state*/
		m_cbxChannel.EnableWindow(TRUE);
		m_btnLogin.EnableWindow(FALSE);
		m_btnLogout.EnableWindow(TRUE);

		m_btnStartRealPlay.EnableWindow(TRUE);
		m_btnStopRealPlay.EnableWindow(FALSE);

		m_btnAttachEvent.EnableWindow(TRUE);
		m_btnDetachEvent.EnableWindow(FALSE);

		InitEventCombox();


		for(int i = 0; i < m_nChannelNum; ++i)
		{
			CString tmp ;
			tmp.Format(ConvertString(_T("Channel %d")), i+1) ;
			m_cbxChannel.AddString(tmp);
			m_cbxChannel.SetItemData(i, (DWORD_PTR)i);
		}
		m_cbxChannel.SetCurSel(0);

		m_EventPic.FreeData();
		InitEventPic();

		OnBtnStartrealplay();
		OnBtnAttachevent();
	}
	else
	{
		ShowLoginErrorReason(err);
	}

}

void CIntelligentEventDlg::OnBtnLogout() 
{
	// TODO: Add your control notification handler code here
	OnBtnStoprealplay();
	SetWindowText(ConvertString(_T("Intelligent Event")));

	BOOL bSuccess = CLIENT_Logout(m_loginID);
	m_loginID = 0;
	m_nChannelNum = 0;
	m_cbxEvent.SetCurSel(0);

	// set login button  and logout button status
	m_btnLogin.EnableWindow(TRUE);
	m_btnLogout.EnableWindow(FALSE);

	// set preview button status
	m_btnStartRealPlay.EnableWindow(FALSE);
	m_btnStopRealPlay.EnableWindow(FALSE);

	m_btnDetachEvent.EnableWindow(FALSE);
	m_btnAttachEvent.EnableWindow(FALSE);

	m_cbxChannel.Clear();
	m_cbxChannel.ResetContent();
	m_cbxChannel.EnableWindow(FALSE);

	m_cbxEvent.Clear();
	m_cbxEvent.ResetContent();
	m_cbxEvent.EnableWindow(FALSE);

	DeleteAllStoreEventData();
	DeleteAllItems();

	m_EventPic.FreeData();
	Invalidate(TRUE);

	m_index = 0;
}

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

	// TODO: Add extra initialization here
	m_dlgShowPic.Create(IDD_SHOWPIC);
	//	m_dlgShowPic.ShowWindow(TRUE);

	g_SetWndStaticText(this);

	InitContorlData();

	InitNetSDK();

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CIntelligentEventDlg::OnBtnStartrealplay() 
{
	// TODO: Add your control notification handler code here

	HWND hWnd = GetDlgItem(IDC_STATIC_PREVIEW)->GetSafeHwnd();
	int nSel = m_cbxChannel.GetCurSel();
	if ( (nSel < 0) || (m_loginID == 0) )
	{
		MessageBox(ConvertString(_T("Please login and select a channel before preview!")),_T("Prompt"));
		return;
	}
	//Open the preview
	int nChannelID = m_cbxChannel.GetItemData(nSel);
	if (m_lPlayID != 0)
	{
		OnBtnStoprealplay();
	}


	//Enable stream
	BOOL bOpenRet = m_playAPI.PLAY_OpenStream(PLAYPORT,0,0,1024*900);
	if(bOpenRet)
	{
		// Render intelligent data
		m_playAPI.PLAY_RenderPrivateData(PLAYPORT,1,0);

		//Begin play 
		BOOL bPlayRet = m_playAPI.PLAY_Play(PLAYPORT,hWnd);

		if(bPlayRet)
		{
			//Real-time play 
			m_lPlayID = CLIENT_RealPlayEx(m_loginID,nChannelID,0);
			if(0 != m_lPlayID)
			{
				//Callback monitor data and then save 
				CLIENT_SetRealDataCallBackEx2(m_lPlayID, CIntelligentEventDlg::RealDataCallBackEx, (LDWORD)this, 0x0f);
				m_btnStartRealPlay.EnableWindow(FALSE);
				m_btnStopRealPlay.EnableWindow(TRUE);
			}
			else
			{
				BOOL bPlay = m_playAPI.PLAY_Stop(PLAYPORT);
				if(bPlay)
				{
					//At last close PLAY_OpenStream
					BOOL bStream = m_playAPI.PLAY_CloseStream(PLAYPORT);
					m_lPlayID = 0;
				}
				MessageBox(ConvertString(_T("Fail to play!")), ConvertString(_T("Prompt")));
				m_btnStartRealPlay.EnableWindow(TRUE);
				m_btnStopRealPlay.EnableWindow(FALSE);
			}
		}
	}
	else
	{
		MessageBox(ConvertString(_T("Open Play Stream failed!")),ConvertString(_T("Prompt")));
	}
}


void CIntelligentEventDlg::OnBtnStoprealplay() 
{
	// TODO: Add your control notification handler code here
	if (m_lPlayID != 0)
	{
		BOOL bRealPlay = CLIENT_StopRealPlayEx(m_lPlayID);

		BOOL bPlay = m_playAPI.PLAY_Stop(PLAYPORT);
		if(bPlay)
		{
			//At last close PLAY_OpenStream
			BOOL bStream = m_playAPI.PLAY_CloseStream(PLAYPORT);
			m_lPlayID = 0;
		}

	}
	m_btnStartRealPlay.EnableWindow(TRUE);
	m_btnStopRealPlay.EnableWindow(FALSE);
	Invalidate(TRUE);

}


void CIntelligentEventDlg::OnBtnAttachevent() 
{
	// TODO: Add your control notification handler code here
	// before attach intelligent event,you must login device first
	// attach device all channel 
	EnterCriticalSection(&m_csAttachList);

	for (handle_list::iterator it = m_attachList.begin(); 
		it != m_attachList.end(); ++it)
	{
		CLIENT_StopLoadPic(*it);
	}
	m_attachList.clear();

	for (int i = 0; i < m_nChannelNum; ++i)
	{
		LLONG lRet = CLIENT_RealLoadPictureEx(m_loginID, i, EVENT_IVS_ALL, TRUE, CIntelligentEventDlg::RealLoadPicCallback, (LDWORD)this, NULL);
		if (lRet == 0)
		{
			MessageBox(ConvertString(_T("Subscribe to Intelligent Event failed!")), ConvertString(_T("Prompt")));
			//	return;
		}
		else
		{
			m_attachList.push_back(lRet);
		}

	}
	LeaveCriticalSection(&m_csAttachList);


	m_btnAttachEvent.EnableWindow(FALSE);
	m_btnDetachEvent.EnableWindow(TRUE);
	m_cbxEvent.EnableWindow(TRUE);

}

void CIntelligentEventDlg::OnBtnDetachevent() 
{
	// TODO: Add your control notification handler code here
	EnterCriticalSection(&m_csAttachList);
	for (handle_list::iterator it = m_attachList.begin(); 
		it != m_attachList.end(); ++it)
	{
		CLIENT_StopLoadPic(*it);
	}
	m_attachList.clear();
	LeaveCriticalSection(&m_csAttachList);

	m_btnAttachEvent.EnableWindow(TRUE);
	m_btnDetachEvent.EnableWindow(FALSE);
	m_cbxEvent.EnableWindow(FALSE);

	m_EventPic.FreeData();
	InitEventPic();

}


void CIntelligentEventDlg::OnSelchangeCbxChannel() 
{
	// TODO: Add your control notification handler code here
	if (FALSE == m_btnStartRealPlay.IsWindowEnabled())
	{
		OnBtnStartrealplay();
	}

}


BOOL CIntelligentEventDlg::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class

	return CDialog::DestroyWindow();
}

void CIntelligentEventDlg::OnDestroy() 
{
	CDialog::OnDestroy();

	// TODO: Add your message handler code here
	DeleteAllItems();
	//OnBtnStoprealplay();
	OnBtnLogout();
	UnInitNetSDK();
	m_dlgShowPic.DestroyWindow();

}	

LRESULT CIntelligentEventDlg::OnDeviceDisConnect(WPARAM wParam, LPARAM lParam)
{
	//	MessageBox("Network disconnected!", "Prompt");
	SetWindowText(ConvertString(_T("Network disconnected!")));
	return 0;
}

LRESULT CIntelligentEventDlg::OnDeviceReconnect(WPARAM wParam, LPARAM lParam)
{	
	//	MessageBox("Reconnect Device Success!", "Prompt");
	SetWindowText(ConvertString(_T("Intelligent Event")));
	return 0;
}

/************************************************************************/
/*handle message WM_USER_ALAMR_COME                                        */
/************************************************************************/
LRESULT CIntelligentEventDlg::OnAlarmCome(WPARAM wParam, LPARAM lParam)
{
	EventPara* ep = (EventPara*)wParam;
	this->DealWithEvent(ep->lAnalyzerHandle, ep->dwAlarmType, ep->pAlarmInfo, ep->pBuffer, ep->dwBufSize, ep->nSequence);

	TraceOut("[OnAlarmCome]try to delete buf:%p, dwbufsize:%d,alarm:%p, ep:%p\r\n", ep->pBuffer,ep->dwBufSize, ep->pAlarmInfo, ep);
	delete[] ep->pBuffer;
	delete[] ep->pAlarmInfo;
	delete ep;
	return 0;
}

/************************************************************************/
/* handle the receive event												*/
/* picture group: one picture, multi  events							*/                     
/* event group:one event, multi pictures			                    */
/************************************************************************/
void CIntelligentEventDlg::DealWithEvent(LLONG lAnalyzerHandle, DWORD dwAlarmType, char* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize, int nSequence)
{
	// get event occur time 

	// some device one picture corresponding  multi events
	// identity the picture 
	if (nSequence == 0) // picture group begin 
	{

	}

	else if (nSequence == 2) // picture group end
	{

	}

	DisplayEventInfo(m_nFilterEventType,dwAlarmType,pAlarmInfo, pBuffer, dwBufSize );

}

void CALL_METHOD CIntelligentEventDlg::RealDataCallBackEx(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize, LLONG lParam, LDWORD dwUser)
{
	if(dwUser == 0)
	{
		return;
	}

	CIntelligentEventDlg *dlg = (CIntelligentEventDlg *)dwUser;
	dlg->ReceiveRealData(lRealHandle,dwDataType, pBuffer, dwBufSize, lParam);
}

//Process after receiving real-time data 
void CIntelligentEventDlg::ReceiveRealData(LLONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, LLONG lParam)
{
	//Stream port number according to the real-time handle.
	//Input the stream data getting from the card
	BOOL bInput=FALSE;
	if(0 != PLAYPORT)
	{
		switch(dwDataType) {
case 0:
	//Original data 
	bInput = m_playAPI.PLAY_InputData(PLAYPORT,pBuffer,dwBufSize);
	break;
case 1:
	//Standard video data 

	break;
case 2:
	//yuv data 

	break;
case 3:
	//pcm audio data 

	break;
case 4:
	//Original audio data 

	break;
default:
	break;
		}	
	}
}

/************************************************************************/
/* SDK回调函数                                                          */
/************************************************************************/
int CALL_METHOD CIntelligentEventDlg::RealLoadPicCallback (LLONG lAnalyzerHandle, DWORD dwAlarmType, void* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize, LDWORD dwUser, int nSequence, void *userdata)
{
	TraceOut("[RealLoadPicCallback]handle:%p, type:%08x, info:%p, buf:%p, size:%u, seq:%d\r\n",
		lAnalyzerHandle, dwAlarmType, pAlarmInfo, pBuffer, dwBufSize, nSequence);


	DWORD nAlarmInfoSize = 0;

	int nRet =  GetAlarmInfoSize(dwAlarmType, &nAlarmInfoSize);
	if (nRet == -1)
	{
		TraceOut("[RealLoadPicCallback]the demo not support this event type:%d \n",dwAlarmType);
		return -1;
	}

	//Get the CIntelligentEventDlg instance
	CIntelligentEventDlg *pEventInstance = (CIntelligentEventDlg*)dwUser;

	EventPara* eventData = new EventPara;
	eventData->lAnalyzerHandle = lAnalyzerHandle;
	eventData->dwAlarmType = dwAlarmType;
	eventData->dwBufSize = dwBufSize;
	eventData->nSequence = nSequence;

	eventData->pBuffer = new BYTE[dwBufSize];
	TraceOut("[RealLoadPicCallback]new pBuf:%p dwBufSize:%u \r\n", eventData->pBuffer,dwBufSize);

	memcpy(eventData->pBuffer, pBuffer, dwBufSize);

	TraceOut("[After memcpy]new pBuf:%p dwBufSize:%u \r\n", eventData->pBuffer,dwBufSize);



	eventData->pAlarmInfo = new char[nAlarmInfoSize];


	memcpy(eventData->pAlarmInfo, pAlarmInfo, nAlarmInfoSize);

	HWND hwnd = pEventInstance->GetSafeHwnd();

	::PostMessage(hwnd, WM_USER_ALAMR_COME, (WPARAM)(eventData), 0);
	return 0;
}



void CIntelligentEventDlg::InitNetSDK()
{
	BOOL bSuccess = CLIENT_Init(&CIntelligentEventDlg::DisConnectFunc,(LDWORD)this);
	CLIENT_SetAutoReconnect(&CIntelligentEventDlg::HaveReConnectFunc, (LDWORD)this);
}

void CIntelligentEventDlg::UnInitNetSDK()
{
	CLIENT_Cleanup();
}


void CIntelligentEventDlg::DeviceDisConnect(LLONG lLoginID, char *sDVRIP,LLONG nDVRPort)
{
	MessageBox(ConvertString(_T("Network disconnected!")), ConvertString(_T("Prompt")));
}


void CALLBACK CIntelligentEventDlg::DisConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
	if(0 != dwUser)
	{
		CIntelligentEventDlg *pDlgInstance = (CIntelligentEventDlg *)dwUser;
		HWND hwnd = pDlgInstance->GetSafeHwnd();
		::PostMessage(hwnd, WM_EVENT_DISCONNECT, 0, 0);	
	}

}

void CALLBACK CIntelligentEventDlg::HaveReConnectFunc(LLONG lLoginID, char *pchDVRIP, LONG nDVRPort, LDWORD dwUser)
{
	if(0 != dwUser)
	{
		CIntelligentEventDlg *pDlgInstance = (CIntelligentEventDlg *)dwUser;
		HWND hwnd = pDlgInstance->GetSafeHwnd();
		::PostMessage(hwnd, WM_EVENT_RECONNECT, 0, 0);
		//    dlg->DeviceDisConnect(lLoginID, pchDVRIP,nDVRPort);
	}

}



CString CIntelligentEventDlg::GetDeviceIP()
{
	CString strRet=_T("");
	BYTE nField0,nField1,nField2,nField3;
	m_IPCtrl.GetAddress(nField0,nField1,nField2,nField3);
	strRet.Format(_T("%d.%d.%d.%d"),nField0,nField1,nField2,nField3);
	return strRet;
}

void CIntelligentEventDlg::ShowLoginErrorReason(int nError)
{
	if(1 == nError)		MessageBox(ConvertString(_T("Invalid password!")), ConvertString(_T("Prompt")));
	else if(2 == nError)	MessageBox(ConvertString(_T("Invalid account!")),ConvertString(_T("Prompt")));
	else if(3 == nError)	MessageBox(ConvertString(_T("Timeout!")), ConvertString(_T("Prompt")));
	else if(4 == nError)	MessageBox(ConvertString(_T("The user has logged in!")),ConvertString(_T("Prompt")));
	else if(5 == nError)	MessageBox(ConvertString(_T("The user has been locked!")), ConvertString(_T("Prompt")));
	else if(6 == nError)	MessageBox(ConvertString(_T("The user has listed into illegal!")), ConvertString(_T("Prompt")));
	else if(7 == nError)	MessageBox(ConvertString(_T("The system is busy!")),ConvertString(_T( "Prompt")));
	else if(9 == nError)	MessageBox(ConvertString(_T("You Can't find the network server!")), ConvertString(_T("Prompt")));
	else	MessageBox(ConvertString(_T("Login failed!")), ConvertString(_T("Prompt")));
}



void CIntelligentEventDlg::DisplayEventInfo(DWORD filterType, DWORD dwAlarmType, char* pAlarmInfo, BYTE *pBuffer, DWORD dwBufSize)
{

	USES_CONVERSION;

	// 0: all, 
	// 1: EVENT_IVS_CROSSLINEDETECTION, 
	// 2: EVENT_IVS_CROSSREGIONDETECTION, 
	// 3: EVENT_IVS_LEFTDETECTION,
	// 4: EVENT_IVS_TAKENAWAYDETECTION,
	// 5: EVENT_IVS_SCENECHANGE,
	// 6: EVENT_IVS_FACEDETECTION,


	std::string strTime;
	std::string strdetail;
	int channel = 1;
	int nRet = GetShowItemInfo(dwAlarmType, pAlarmInfo, strTime,channel,strdetail);


	GUID guid = {0};
	HRESULT hr =  CoCreateGuid(&guid);
	char bufGUID[64] = {0};
	sprintf_s(
		bufGUID,
		"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
		guid.Data1, guid.Data2, guid.Data3,
		guid.Data4[0], guid.Data4[1],
		guid.Data4[2], guid.Data4[3],
		guid.Data4[4], guid.Data4[5],
		guid.Data4[6], guid.Data4[7]);

	std::string strGUID(bufGUID);


	m_index++;
	StoreEventInfoToList(channel,dwAlarmType,pBuffer,dwBufSize,strGUID,strTime,strdetail );


	if (filterType == EVENT_IVS_ALL || filterType == dwAlarmType)
	{

		m_EventPic.Load(pBuffer, dwBufSize);

		LV_ITEM lvi;
		lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
		lvi.iSubItem = 0;
		lvi.pszText = _T("");
		lvi.iImage = 0;
		lvi.iItem = 0;

		CString cstrChannel ;
		cstrChannel.Format(_T("%d"),channel);

		CString cstrIndex;
		cstrIndex.Format(_T("%d"), m_index);

		EnterCriticalSection(&m_csLCEventInfo);
		m_lcEventInfo.InsertItem(&lvi);

		m_lcEventInfo.SetItemText(0,0,cstrIndex);
		m_lcEventInfo.SetItemText(0,1,cstrChannel);
		m_lcEventInfo.SetItemText(0,2, A2T(strdetail.c_str()));
		m_lcEventInfo.SetItemText(0,3, A2T(strTime.c_str()));

		char* itemData = new char[GUIDLEN];
		memset(itemData, 0, GUIDLEN - 1);
		strncpy(itemData, strGUID.c_str(), GUIDLEN -1);
		m_lcEventInfo.SetItemData(0, (DWORD_PTR)itemData);

		if (m_lcEventInfo.GetItemCount() > LISTSIZE)
		{
			char* pCh = (char*) m_lcEventInfo.GetItemData(LISTSIZE);
			delete[] pCh;

			m_lcEventInfo.DeleteItem(LISTSIZE);

		}
		LeaveCriticalSection(&m_csLCEventInfo);


	}

}


int  CIntelligentEventDlg::GetAlarmInfoSize( DWORD AlarmType, DWORD *pAlarmSize)
{
	switch(AlarmType)
	{
	case EVENT_IVS_CROSSLINEDETECTION:
		{
			*pAlarmSize = sizeof(DEV_EVENT_CROSSLINE_INFO);
		}
		break;
	case EVENT_IVS_CROSSREGIONDETECTION:
		{
			*pAlarmSize = sizeof(DEV_EVENT_CROSSREGION_INFO);
		}
		break;
	case EVENT_IVS_LEFTDETECTION :
		{
			*pAlarmSize	= sizeof(DEV_EVENT_LEFT_INFO);
		}
		break;
	case EVENT_IVS_TAKENAWAYDETECTION:
		{
			*pAlarmSize = sizeof(DEV_EVENT_TAKENAWAYDETECTION_INFO);
		}
		break;
	case EVENT_IVS_SCENE_CHANGE:
		{
			*pAlarmSize = sizeof(DEV_ALRAM_SCENECHANGE_INFO);
		}
		break;
	case EVENT_IVS_FACEDETECT:
		{
			*pAlarmSize = sizeof(DEV_EVENT_FACEDETECT_INFO);
		}
		break;
	default:
		return -1; // demo not support this event type 
	}

	return 0;
}




int  CIntelligentEventDlg::GetShowItemInfo(DWORD AlarmType,char* pAlarmInfo, std::string& strTime, int& channel, std::string& strDetail)
{
	char szTime[128] = {0};

	switch(AlarmType)
	{
	case EVENT_IVS_CROSSLINEDETECTION:
		{
			DEV_EVENT_CROSSLINE_INFO* pInfo = (DEV_EVENT_CROSSLINE_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->UTC.dwYear,
				pInfo->UTC.dwMonth,
				pInfo->UTC.dwDay,
				pInfo->UTC.dwHour,
				pInfo->UTC.dwMinute,
				pInfo->UTC.dwSecond,
				pInfo->UTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			strDetail = "Tripwire detection";
		}
		break;
	case EVENT_IVS_CROSSREGIONDETECTION:
		{
			DEV_EVENT_CROSSREGION_INFO* pInfo = (DEV_EVENT_CROSSREGION_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->UTC.dwYear,
				pInfo->UTC.dwMonth,
				pInfo->UTC.dwDay,
				pInfo->UTC.dwHour,
				pInfo->UTC.dwMinute,
				pInfo->UTC.dwSecond,
				pInfo->UTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			strDetail = "Intrusion detection";
		}
		break;
	case EVENT_IVS_LEFTDETECTION :
		{
			DEV_EVENT_LEFT_INFO* pInfo = (DEV_EVENT_LEFT_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->UTC.dwYear,
				pInfo->UTC.dwMonth,
				pInfo->UTC.dwDay,
				pInfo->UTC.dwHour,
				pInfo->UTC.dwMinute,
				pInfo->UTC.dwSecond,
				pInfo->UTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			strDetail = "Abandoned Object detection";

		}
		break;
	case EVENT_IVS_TAKENAWAYDETECTION:
		{
			DEV_EVENT_TAKENAWAYDETECTION_INFO* pInfo = (DEV_EVENT_TAKENAWAYDETECTION_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->UTC.dwYear,
				pInfo->UTC.dwMonth,
				pInfo->UTC.dwDay,
				pInfo->UTC.dwHour,
				pInfo->UTC.dwMinute,
				pInfo->UTC.dwSecond,
				pInfo->UTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			strDetail = "Missing Object detection";

		}
		break;
	case EVENT_IVS_SCENE_CHANGE:
		{
			DEV_ALRAM_SCENECHANGE_INFO* pInfo = (DEV_ALRAM_SCENECHANGE_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->stuUTC.dwYear,
				pInfo->stuUTC.dwMonth,
				pInfo->stuUTC.dwDay,
				pInfo->stuUTC.dwHour,
				pInfo->stuUTC.dwMinute,
				pInfo->stuUTC.dwSecond,
				pInfo->stuUTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			if (pInfo->nEventAction == 1)
			{
				strDetail = "Scene changing:begin";
			}
			else if (pInfo->nEventAction == 2)
			{
				strDetail = "Scene changing: end";
			}
			else 
			{
				strDetail = "Scene changing detection";
			}


		}
		break;
	case EVENT_IVS_FACEDETECT:
		{
			DEV_EVENT_FACEDETECT_INFO* pInfo = (DEV_EVENT_FACEDETECT_INFO*)pAlarmInfo;
			sprintf_s(szTime, 
				"%04d-%02d-%02d %02d:%02d:%02d.%3d",
				pInfo->UTC.dwYear,
				pInfo->UTC.dwMonth,
				pInfo->UTC.dwDay,
				pInfo->UTC.dwHour,
				pInfo->UTC.dwMinute,
				pInfo->UTC.dwSecond,
				pInfo->UTC.dwMillisecond);
			channel = pInfo->nChannelID + 1;
			strDetail = "Face detection";

		}
		break;
	default:
		return -1; // demo not support this event type 
	}

	strTime = szTime;


	return 0;

}

bool CIntelligentEventDlg::StoreEventInfoToList(int channel, int EventID, BYTE* EventData,DWORD dataSize,
											 std::string& strGUID,std::string& strTime, std::string& strDetail)
{

	int i = -1;

	EventType2Index(EventID, &i);
	if ( i == -1)
	{
		return false;
	}

	EventDataInfo eventInfo;
	eventInfo.nChannel = channel;
	eventInfo.EventID = EventID;
	eventInfo.strGUID = strGUID;
	eventInfo.strTime = strTime;
	eventInfo.strDetail = strDetail;
	eventInfo.index = m_index;

	eventInfo.Data = new BYTE[dataSize];
	memcpy(eventInfo.Data , EventData, dataSize);
	eventInfo.dataSize = dataSize;


	EnterCriticalSection(&m_csEventList);
	m_eventList[i].push_front(eventInfo);
	m_allEvents.push_front(&(*(m_eventList[i].begin())));

	if (m_eventList[i].size() > LISTSIZE)
	{
		EventList::reverse_iterator it= m_eventList[i].rbegin();

		m_allEvents.remove(&(*it));

		delete[] it->Data;
		m_eventList[i].pop_back();
	}
	LeaveCriticalSection(&m_csEventList);


	return true;
}

void CIntelligentEventDlg::InitContorlData()
{
	m_IPCtrl.SetAddress(10,34,3,49);

	InitEventListCtrl();

	InitEventPic();

}

void CIntelligentEventDlg::InitEventListCtrl()
{
	m_lcEventInfo.SetExtendedStyle(m_lcEventInfo.GetExtendedStyle()|LVS_EX_FULLROWSELECT);  
	m_lcEventInfo.SetExtendedStyle(m_lcEventInfo.GetExtendedStyle()|LVS_EX_GRIDLINES); 

	CRect rect;
	int width ;
	m_lcEventInfo.GetClientRect(&rect);
	width = rect.Width();

	LV_COLUMN lvc;
	lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
	lvc.fmt=LVCFMT_LEFT;

	CString strToConvert = ConvertString(_T("Index"));
	lvc.pszText = (LPTSTR)(LPCTSTR)strToConvert;
	lvc.cx = width/4 - 20;
	lvc.iSubItem = 0;
	m_lcEventInfo.InsertColumn(0, &lvc);

	strToConvert = ConvertString(_T("Channel"));
	lvc.pszText = (LPTSTR)(LPCTSTR)strToConvert;
	lvc.cx = width/4 - 20;
	lvc.iSubItem = 0;
	m_lcEventInfo.InsertColumn(1, &lvc);

	strToConvert = ConvertString(_T("Event name"));
	lvc.pszText = (LPTSTR)(LPCTSTR)strToConvert;
	lvc.cx = width/4 + 20;
	lvc.iSubItem = 0;
	m_lcEventInfo.InsertColumn(2, &lvc);

	strToConvert = ConvertString(_T("UTC"));
	lvc.pszText = (LPTSTR)(LPCTSTR)strToConvert;
	lvc.cx = width/4 + 20;
	lvc.iSubItem = 0;
	m_lcEventInfo.InsertColumn(3, &lvc);
}


void CIntelligentEventDlg::InitEventPic()
{
	m_EventPic.FreeData();
}


void CIntelligentEventDlg::InitEventCombox()
{
	CString tmp  = ConvertString(_T("All Events"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(0, (DWORD_PTR)EVENT_IVS_ALL);

	tmp = ConvertString(_T("Tripwire"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(1, (DWORD_PTR)EVENT_IVS_CROSSLINEDETECTION);

	tmp = ConvertString(_T("Intrusion"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(2, (DWORD_PTR)EVENT_IVS_CROSSREGIONDETECTION);

	tmp = ConvertString(_T("Abandoned Object"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(3, (DWORD_PTR)EVENT_IVS_LEFTDETECTION);

	tmp = ConvertString(_T("Missing Object"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(4, (DWORD_PTR)EVENT_IVS_TAKENAWAYDETECTION);

	tmp = ConvertString(_T("Scene Change"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(5, (DWORD_PTR)EVENT_IVS_SCENE_CHANGE);

	tmp = ConvertString(_T("Face Detection"));
	m_cbxEvent.AddString(tmp);
	m_cbxEvent.SetItemData(6, (DWORD_PTR)EVENT_IVS_FACEDETECT);

	m_cbxEvent.SetCurSel(0);
}




void CIntelligentEventDlg::OnCbnSelchangeCbxEvent()
{
	USES_CONVERSION;
	// TODO: 在此添加控件通知处理程序代码
	if (m_loginID == 0)
	{
		return ;
	}


	DWORD eventType = m_cbxEvent.GetItemData(m_cbxEvent.GetCurSel());

	if (eventType == m_nFilterEventType)
	{
		return;
	}


	m_nFilterEventType = eventType;

	EnterCriticalSection(&m_csLCEventInfo);

	DeleteAllItems();
	int i = -1;


	EventType2Index(eventType,&i );

	EnterCriticalSection(&m_csEventList);
	if (i < 6)
	{
		InitEventPic();
		CString cstrChannel;
		CString cstrIndex;

		EventList::iterator it = m_eventList[i].begin(); 

		for (int j = 0; it != m_eventList[i].end();++it,++j)
		{
			LV_ITEM lvi;
			lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
			lvi.iSubItem = 0;
			lvi.pszText = _T("");
			lvi.iImage = 0;
			lvi.iItem = j;


			cstrChannel.Format(_T("%d"),it->nChannel);
			cstrIndex.Format(_T("%d"), it->index);

			m_lcEventInfo.InsertItem(&lvi);
			m_lcEventInfo.SetItemText(j,0,cstrIndex);
			m_lcEventInfo.SetItemText(j,1,cstrChannel);
			m_lcEventInfo.SetItemText(j,2, A2T(it->strDetail.c_str()));
			m_lcEventInfo.SetItemText(j,3, A2T(it->strTime.c_str()));

			char* itemData = new char[GUIDLEN];
			memset(itemData, 0, GUIDLEN);
			strncpy(itemData, it->strGUID.c_str(), GUIDLEN -1);
			m_lcEventInfo.SetItemData(j, (DWORD_PTR)(itemData));

		}

	}

	else if ( i = 6)
	{
		AllEventsInfo::iterator it = m_allEvents.begin();

		CString cstrChannel;
		CString cstrIndex;

		for (int j = 0 ; it != m_allEvents.end() && j < LISTSIZE; ++it,++j)
		{
			LV_ITEM lvi;
			lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
			lvi.iSubItem = 0;
			lvi.pszText = _T("");
			lvi.iImage = 0;
			lvi.iItem = j;

			cstrChannel.Format(_T("%d"),(*it)->nChannel);
			cstrIndex.Format(_T("%d"), (*it)->index);

			m_lcEventInfo.InsertItem(&lvi);
			m_lcEventInfo.SetItemText(j,0,cstrIndex);
			m_lcEventInfo.SetItemText(j,1,cstrChannel);
			m_lcEventInfo.SetItemText(j,2, A2T((*it)->strDetail.c_str()));
			m_lcEventInfo.SetItemText(j,3, A2T((*it)->strTime.c_str()));

			char* itemData = new char[GUIDLEN];
			memset(itemData, 0, GUIDLEN-1);
			strncpy(itemData, (*it)->strGUID.c_str(), GUIDLEN-1);
			m_lcEventInfo.SetItemData(j, (DWORD_PTR)itemData);
		}
	}
	LeaveCriticalSection(&m_csEventList);


	LeaveCriticalSection(&m_csLCEventInfo);


}

void CIntelligentEventDlg::DeleteAllItems()
{

	int nItemCount = m_lcEventInfo.GetItemCount();
	for ( int i = nItemCount - 1; i >= 0; i-- )
	{
		char* pCh = (char*) m_lcEventInfo.GetItemData(i);
		delete[] pCh;
		pCh = NULL;
		//delete[] (char*)(m_lcResult.GetItemData(i));
	}
	m_lcEventInfo.DeleteAllItems();
}

void CIntelligentEventDlg::DeleteAllStoreEventData()
{
	m_allEvents.clear();

	for (int i = 0 ; i < 6 ; i++)
	{
		EventList::iterator it = m_eventList[i].begin();

		for (; it != m_eventList[i].end(); ++it)
		{
			delete[] it->Data;
		}

		m_eventList[i].clear();
	}

}


void CIntelligentEventDlg::OnNMDblclkListEventinfo(NMHDR *pNMHDR, LRESULT *pResult)
{
	// TODO: 在此添加控件通知处理程序代码
	NM_LISTVIEW* pNMListView  = (NM_LISTVIEW*)pNMHDR;

	int nItem = pNMListView->iItem;

	if (nItem < 0 ||  nItem >= m_lcEventInfo.GetItemCount())
	{
		return ;
	}

	char* pGuid = (char*)m_lcEventInfo.GetItemData(nItem);

	EnterCriticalSection(&m_csEventList);
	if ( m_nFilterEventType == EVENT_IVS_ALL)
	{
		AllEventsInfo::iterator	 it = m_allEvents.begin();
		for (; it != m_allEvents.end(); ++it)
		{
			if (strncmp((*it)->strGUID.c_str(), pGuid, (*it)->strGUID.size()) == 0)
			{
				CRect rect;
				m_dlgShowPic.GetWindowRect(&rect);

				m_dlgShowPic.SetWindowPos(NULL, rect.top,rect.top,0,0,SWP_NOSIZE);
				m_dlgShowPic.ShowWindow(TRUE);
				m_dlgShowPic.ShowPicture((*it)->Data,(*it)->dataSize);

				break;
			}
		}

	}
	else 
	{
		int i = m_cbxEvent.GetCurSel() - 1;
		EventList::iterator it = m_eventList[i].begin();

		for (; it != m_eventList[i].end(); ++it)
		{
			if (strcmp(it->strGUID.c_str(), pGuid) == 0)
			{
				CRect rect;
				m_dlgShowPic.GetWindowRect(&rect);

				m_dlgShowPic.SetWindowPos(NULL, rect.top,rect.top,0,0,SWP_NOSIZE);
				m_dlgShowPic.ShowWindow(TRUE);
				m_dlgShowPic.ShowPicture(it->Data,it->dataSize);

				break;
			}
		}

	}
	LeaveCriticalSection(&m_csEventList);
	*pResult = 0;
}

void CIntelligentEventDlg::EventType2Index(DWORD type, int* pIndex)
{
	switch (type)
	{
	case EVENT_IVS_ALL:
		{
			*pIndex = 6;
		}
		break;

	case EVENT_IVS_CROSSLINEDETECTION:
		{
			*pIndex = 0;
		}
		break;

	case EVENT_IVS_CROSSREGIONDETECTION:
		{
			*pIndex = 1;
		}
		break;

	case EVENT_IVS_LEFTDETECTION:
		{
			*pIndex = 2;
		}
		break;

	case EVENT_IVS_TAKENAWAYDETECTION:
		{
			*pIndex = 3;
		}
		break;

	case EVENT_IVS_SCENE_CHANGE:
		{
			*pIndex = 4;
		}
		break;

	case EVENT_IVS_FACEDETECT:
		{
			*pIndex = 5;
		}
		break;

	default:
		{
			*pIndex = -1;
		}
		break;
	}
}


