/*******************************************************************

Copyright (c) 2004 Open Mobile Alliance, Ltd.  All Rights Reserved.

This software is made available under the usage and distribution terms 
covered by the Common Public License 1.0 and by using this software you
are bound by the terms and conditions of the same.

EXCEPT AS EXPRESSLY SET FORTH IN THE COMMON PUBLIC LICENSE,
THIS PROGRAM IS PROVIDED ON AN "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, 
ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   
Each recipient is solely responsible for determining the 
appropriateness of using and distributing this program and assumes 
all risks associated with its exercise of rights under the Common 
Public License, including but not limited to the risks and 
costs of program errors, compliance with applicable laws, 
damage to or loss of data, programs or equipment, and 
unavailability or interruption of operations.

********************************************************************/
// TestPane.cpp : implementation file
//

#include "stdafx.h"
#include "SCTS3DevMan.h"
#include "TestPane.h"
//#include "TestPreReq.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTestPane dialog
struct testCallbackData
{
	CTestPane *testPane;
	HTREEITEM errorLogUI;
	SctsErrorLog *errorLog;
	SctsDMTester *tester;
};

static char testEngineStateDesc[4][50]=
{
	"Idle",
	"Terminating...",
	"Prerequisite session...",
	"Test session...",
};

static void uiErrorCallback(void *data,SctsDMSession *session)
{
	struct testCallbackData *uiCallbackData=(struct testCallbackData *)data;
	if (!uiCallbackData) return;
	if (session && !session->IsSuccessful())
	{
		uiCallbackData->errorLog=session->errorLog;
		componentUIC.removeSession(session);
		uiCallbackData->errorLogUI=(HTREEITEM)uiCallbackData->errorLog->uiData;
	}
}

static void uiCallback(void *data,SctsDMSession *session)
{
	SctsDMTester *tester=((struct testCallbackData *)data)->tester;
	::SendMessage(((struct testCallbackData *)data)->testPane->m_hWnd,WM_TESTCOMPLETE,(WPARAM)session,0);
}

CTestPane::CTestPane(SctsDMTester *_tester,CWnd* pParent /*=NULL*/)
	: CDialog(CTestPane::IDD, pParent),tester(_tester)
{
	//{{AFX_DATA_INIT(CTestPane)
	m_desc = _T("");
	m_state = _T("");
	//}}AFX_DATA_INIT
}


void CTestPane::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTestPane)
	DDX_Control(pDX, IDC_TESTLIST, m_list);
	DDX_Control(pDX, IDC_TESTGROUPLIST, m_grouplist);
	DDX_Text(pDX, IDC_TESTDESC, m_desc);
	DDX_Text(pDX, IDC_TESTSTATE, m_state);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CTestPane, CDialog)
	//{{AFX_MSG_MAP(CTestPane)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_TESTGROUPLIST, OnItemchangedTestgrouplist)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_TESTTEST, OnTesttest)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_TESTLIST, OnItemchangedTestlist)
	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_TESTERRORS, OnTesterrors)
	ON_NOTIFY(NM_DBLCLK, IDC_TESTGROUPLIST, OnDblclkTestgrouplist)
	ON_BN_CLICKED(IDC_TESTSTOP, OnTeststop)
	ON_BN_CLICKED(IDC_TESTRESET, OnTestreset)
	ON_BN_CLICKED(IDC_TESTREPORT, OnTestreport)
	ON_MESSAGE(WM_TESTCOMPLETE,TestComplete)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTestPane message handlers
void CTestPane::Refresh()
{
	int nextTestGroupID=tester->GetNextTestGroupID();
	int item;
	int id;
	int image;
	SctsDMTestInfo *_testInfo;
	item=m_grouplist.GetItemCount();
	while (item--)
	{
		id=m_grouplist.GetItemData(item);
		image=2;
		for (_testInfo=tester->testInfo;_testInfo;_testInfo=_testInfo->next)
		{
			if (_testInfo->id/100==id)
			{
				if (_testInfo->state==TEST_FAILED)
				{
					image=3;
					break;
				}
				if (_testInfo->state==NOT_TESTED) image=1;
				if (_testInfo->state==TEST_OPTIONAL) image=4;
				if (_testInfo->state==NOT_SUPPORTED) 
				{
					image=5;
					break;
				}
			}
		}
		if (id==nextTestGroupID)
		{
			m_grouplist.SetItem(item,0,LVIF_IMAGE | LVIF_STATE,0,image,INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED,LVIS_SELECTED | LVIS_STATEIMAGEMASK,0);
			m_grouplist.SetSelectionMark(item);
		}
		else
			m_grouplist.SetItem(item,0,LVIF_IMAGE | LVIF_STATE,0,image,0,LVIS_SELECTED | LVIS_STATEIMAGEMASK,0);
	}
	GetDlgItem(IDC_TESTTEST)->EnableWindow(tester->GetState()==TE_IDLE);
	m_grouplist.RedrawItems(0,m_grouplist.GetItemCount()-1);
}



BOOL CTestPane::OnInitDialog() 
{
    static const int GROUP_COUNT = 50;
	CDialog::OnInitDialog();
	SctsDMTestInfo *_testInfo;
	bool testGroup[GROUP_COUNT];
	char buffer[20];
	int i,item;
	struct testCallbackData *uiCallbackData;
	LOGFONT logFont;
	
	CFont *font=GetDlgItem(IDC_TESTINFO)->GetFont();
	CFont tempFont;
	font->GetLogFont(&logFont);
	logFont.lfWeight=FW_BOLD;
	tempFont.CreateFontIndirect(&logFont);
	GetDlgItem(IDC_TESTINFO)->SetFont(&tempFont);
	GetDlgItem(IDC_TESTDESCINFO)->SetFont(&tempFont);

	imgList.Create(16,16,ILC_MASK | ILC_COLOR8,4,0);
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_OUT)));
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_UNKNOWN)));
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_PASSED)));
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_FAILED)));
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_OPTIONAL)));
	imgList.Add(LoadIcon(AfxGetResourceHandle(),MAKEINTRESOURCE(IDI_NOTSUPPORTED)));

	
	m_grouplist.SetImageList(&imgList,LVSIL_SMALL);
	m_grouplist.SetImageList(&imgList,LVSIL_STATE);
	m_grouplist.InsertColumn(0,"Test Group",LVCFMT_LEFT,76);
	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | m_list.GetExtendedStyle());
	m_list.SetImageList(&imgList,LVSIL_SMALL);
	m_list.InsertColumn(0,"Test Case",LVCFMT_LEFT,76);
	m_list.InsertColumn(1,"Description",LVCFMT_LEFT,150);
	m_list.InsertColumn(2,"Sequence Time Stamp",LVCFMT_LEFT,150);
	
	memset(testGroup,0,sizeof(bool [GROUP_COUNT]));
	//tester->Lock();
	for (_testInfo=tester->testInfo;_testInfo;_testInfo=_testInfo->next)
		testGroup[_testInfo->id/100]=true;
	//tester->Unlock();
	item=0;
	for (i=0;i<GROUP_COUNT;i++)
	{
		if (testGroup[i])
		{
			sprintf(buffer,"ID : %d",i);
			m_grouplist.InsertItem(item,buffer,testGroup[i]);
			m_grouplist.SetItemData(item++,(DWORD)i);
		}
	}
	Refresh();

	uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0);
	if (!uiCallbackData)
	{
		uiCallbackData=(struct testCallbackData *)malloc(sizeof(struct testCallbackData));
		uiCallbackData->errorLogUI=0;
		uiCallbackData->errorLog=0;
	}
	else if (uiCallbackData->errorLogUI)
	{
        if (mainPane->currentLeftPane->m_sessionTree.GetItemText(uiCallbackData->errorLogUI).GetLength()!=0 &&
            mainPane->currentLeftPane->m_sessionTree.GetItemData(uiCallbackData->errorLogUI)==(DWORD)uiCallbackData->errorLog)
			GetDlgItem(IDC_TESTERRORS)->ShowWindow(SW_SHOW);
		else
		{
			uiCallbackData->errorLogUI=0;
			uiCallbackData->errorLog=0;
		}
	}
	uiCallbackData->tester=tester;
	uiCallbackData->testPane=this;
	GetDlgItem(IDC_TESTSTOP)->EnableWindow(tester->GetState()>TE_TERMINATE);
	GetDlgItem(IDC_TESTRESET)->EnableWindow(tester->GetState()==TE_IDLE);
	GetDlgItem(IDC_TESTREPORT)->EnableWindow(tester->GetState()==TE_IDLE);
	GetDlgItem(IDC_TESTNODE)->SetWindowText(tester->testNode);

	tester->SetUICallback(uiCallbackData,uiCallback);

	m_state=testEngineStateDesc[(int)tester->GetState()];
	UpdateData(FALSE);
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CTestPane::OnItemchangedTestgrouplist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CString passCriteria="";
	char buffer[10];
	int item;
	SctsDMTestGroup *testGroup;
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	*pResult = 0;
	if (!(pNMListView->uNewState & LVIS_SELECTED)) return;
	SelectTestGroup((int)pNMListView->lParam);
	testGroup=SctsDMTestGroup::GetTestGroup(tester->device,(int)pNMListView->lParam);
	delete testGroup;
	m_desc="";
	m_desc="Test group #";
	m_desc+=itoa((int)pNMListView->lParam,buffer,10);

	m_desc+="\r\n\r\nPre-conditions :";
	for (item=0;item<m_list.GetItemCount();++item)
	{
		if (((SctsDMTestPreReq *)m_list.GetItemData(item))->preReqStr[0])
		{
			m_desc+="\r\n";
			m_desc+="Test Case #";
			m_desc+=itoa(((SctsDMTestPreReq *)m_list.GetItemData(item))->id,buffer,10);
			m_desc+=" : ";
			m_desc+=((SctsDMTestPreReq *)m_list.GetItemData(item))->preReqStr;
		}
		passCriteria+="\r\n";
		passCriteria+="Test Case #";
		passCriteria+=itoa(((SctsDMTestPreReq *)m_list.GetItemData(item))->id,buffer,10);
		passCriteria+=" : ";
		passCriteria+=((SctsDMTestPreReq *)m_list.GetItemData(item))->passCriteria;
	}

	if (m_desc.Right(16)=="Pre-conditions :") m_desc+="\r\nNone.";
	m_desc+="\r\n\r\nPass Criteria :"+passCriteria;
	UpdateData(FALSE);

}

void CTestPane::SelectTestGroup(int id)
{
	SctsDMTestPreReq *preReq;
	SctsDMTestInfo *_testInfo;
	char buffer[20];
	int item=0;
	m_list.DeleteAllItems();
	//tester->Lock();
	for (_testInfo=tester->testInfo;_testInfo;_testInfo=_testInfo->next)
	{
		if (_testInfo->id/100==id)
		{
			if (tester->sctsIsServer)
				preReq=sctsClientTestCasePreReqs;
			else
				preReq=sctsServerTestCasePreReqs;
			for (;preReq->id && preReq->id!=_testInfo->id;++preReq);
			SCTSASSERT(preReq->id);
			sprintf(buffer,"ID : %d",_testInfo->id);
			m_list.InsertItem(item,buffer,1+(int)_testInfo->state);
			m_list.SetItem(item,1,LVIF_TEXT,preReq->shortDesc,0,0,0,0);
			m_list.SetItemData(item,(DWORD)preReq);
			if (_testInfo->timeStamp)
			{
				char *timeStamp=sctsGetTimeStamp(true,_testInfo->timeStamp);
				m_list.SetItem(item,2,LVIF_TEXT,timeStamp,0,0,0,0);
				sctsFree(timeStamp);
			}
			++item;
		}
	}
//	tester->Unlock();
	m_list.UpdateWindow();
}	

void CTestPane::OnDestroy() 
{
	struct testCallbackData *uiCallbackData;
	CDialog::OnDestroy();
	uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0);
	uiCallbackData->testPane=0;
	tester->SetUICallback(uiCallbackData,uiErrorCallback);
}

/* 
Create the test session as a new thread because if test pre-requisites are to
be displayed in a modeless dialog then the test session thread will have to
be blocked until the test pre-requisties dialog is closed. If a new thread is
not created it will result in the blocking of the UI thread.
*/
UINT TestTestProc(LPVOID pParam)
{
	((SctsDMTester *)pParam)->ExecuteTestGroup();
	return 0;
}

void CTestPane::OnTesttest() 
{
	struct testCallbackData *uiCallbackData;
	/* Check if there is an account node */
	if (!tester->device->IsServerDevice())
	{
		if (!((SctsDMClientDevice *)tester->device)->accountNode)
		{
			MessageBox("Select a DM Account before running tests.","Tests",MB_ICONSTOP);
			return;
		}
	}
	uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0);
	SCTSASSERT(uiCallbackData);
	uiCallbackData->errorLogUI=0;
	uiCallbackData->errorLog=0;
	tester->SetUICallback(uiCallbackData,uiCallback);
	GetDlgItem(IDC_TESTTEST)->EnableWindow(FALSE);
	GetDlgItem(IDC_TESTERRORS)->ShowWindow(SW_HIDE);
	AfxBeginThread(TestTestProc,(LPVOID)tester);
}

LRESULT CTestPane::TestComplete(WPARAM wParam,LPARAM lParam)
{
    SctsDMSession *session = (SctsDMSession *)wParam;
	struct testCallbackData *uiCallbackData;
	GetDlgItem(IDC_TESTSTOP)->EnableWindow(TRUE);
	GetDlgItem(IDC_TESTRESET)->EnableWindow(FALSE);
	GetDlgItem(IDC_TESTREPORT)->EnableWindow(FALSE);
	m_state=testEngineStateDesc[(int)tester->GetState()];
	if (session && !session->IsSuccessful()) 
	{
		m_state+="Error";
		uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0,true);
		uiCallbackData->errorLog=session->errorLog;
		componentUIC.removeSession(session);
		uiCallbackData->errorLogUI=(HTREEITEM)uiCallbackData->errorLog->uiData;
		GetDlgItem(IDC_TESTERRORS)->ShowWindow(SW_SHOW);
		tester->SetUICallback(uiCallbackData,uiCallback,true);
		GetDlgItem(IDC_TESTSTOP)->EnableWindow(FALSE);
	}
	if (tester->GetState()==TE_IDLE)
	{
		Refresh();
		m_state="Idle";
		GetDlgItem(IDC_TESTSTOP)->EnableWindow(FALSE);
		GetDlgItem(IDC_TESTRESET)->EnableWindow(TRUE);
		GetDlgItem(IDC_TESTREPORT)->EnableWindow(TRUE);
	}
	UpdateData(FALSE);
	return 0;
}


void CTestPane::OnItemchangedTestlist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	SctsDMTestPreReq *preReq;
	char buffer[10];
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	*pResult = 0;
	if (!(pNMListView->uNewState & LVIS_SELECTED)) return;
	preReq=(SctsDMTestPreReq *)pNMListView->lParam;
	m_desc="Test case #";
	m_desc+=itoa(preReq->id,buffer,10);
	m_desc+="\r\n\r\nPurpose :\r\n";
	m_desc+=preReq->desc;
	m_desc+="\r\n\r\nPre-conditions :";
	if (preReq->preReqStr[0])
	{
		m_desc+="\r\n";
		m_desc+=preReq->preReqStr;
	}
	if (m_desc.Right(16)=="Pre-conditions :") m_desc+="\r\nNone.";
	m_desc+="\r\n\r\nPass Criteria :\r\n";
	m_desc+=preReq->passCriteria;
	UpdateData(FALSE);
}

void CTestPane::OnSize(UINT nType, int cx, int cy) 
{
	RECT rect;
	CWnd *temp;
	int width;
	int height;
	CDialog::OnSize(nType, cx, cy);
	if (!m_list.m_hWnd) return;
	GetClientRect(&rect);
	width=rect.right;
	height=rect.bottom;
	temp=GetDlgItem(IDC_TESTDESC);
	temp->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.right=width-rect.left;
	rect.bottom=height-rect.left;
	temp->MoveWindow(&rect);
	temp=GetDlgItem(IDC_TESTINFO);
	temp->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.right=width-rect.left;
	temp->MoveWindow(&rect);
	temp=GetDlgItem(IDC_TESTDESCINFO);
	temp->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.right=width-rect.left;
	rect.bottom=height-rect.left;
	temp->MoveWindow(&rect);
	width-=rect.left;
	m_list.GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.right=width;
	m_list.MoveWindow(&rect);
}

BOOL CTestPane::PreTranslateMessage(MSG* pMsg) 
{
	/* Disable ESC  and Enter */
	if (pMsg->message==WM_KEYDOWN && (pMsg->wParam==VK_ESCAPE || pMsg->wParam==VK_RETURN)) return TRUE;
	
	return CDialog::PreTranslateMessage(pMsg);
}

void CTestPane::OnTesterrors() 
{
	struct testCallbackData *uiCallbackData;
	uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0);
	SCTSASSERT(uiCallbackData);
	if (!uiCallbackData->errorLogUI ||
        mainPane->currentLeftPane->m_sessionTree.GetItemText(uiCallbackData->errorLogUI).GetLength()==0 ||
        mainPane->currentLeftPane->m_sessionTree.GetItemData(uiCallbackData->errorLogUI)!=(DWORD)uiCallbackData->errorLog)
	{
		uiCallbackData->errorLogUI=0;
		uiCallbackData->errorLog=0;
		tester->SetUICallback(uiCallbackData,uiCallback);
		GetDlgItem(IDC_TESTERRORS)->ShowWindow(SW_HIDE);
		return;
	}
	tester->SetUICallback(uiCallbackData,uiCallback);
	mainPane->currentLeftPane->m_sessionTree.SelectItem(uiCallbackData->errorLogUI);
}

void CTestPane::OnDblclkTestgrouplist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int id=m_grouplist.GetSelectionMark();
	*pResult = 0;
	if (tester->GetState()!=TE_IDLE || id==-1) return;
	tester->SetNextTestGroupID(m_grouplist.GetItemData(id));
	Refresh();
}

void CTestPane::OnTeststop() 
{
	if (tester->device && tester->device->IsServerDevice())
	{
		std::list<SctsDMCommand *>::iterator cmdIt;
		while (!((SctsDMServerDevice *)tester->device)->cmdList.empty())
		{
			cmdIt=((SctsDMServerDevice *)tester->device)->cmdList.begin();
			(*cmdIt)->RollBack();
			delete (*cmdIt);
			((SctsDMServerDevice *)tester->device)->cmdList.erase(cmdIt);
		}
	}
	GetDlgItem(IDC_TESTSTOP)->EnableWindow(FALSE);
	tester->SetState(TE_TERMINATE);
}

void CTestPane::OnTestreset() 
{
	//SctsDMTestInfo *_testInfo;
	struct testCallbackData *uiCallbackData;
	uiCallbackData=(struct testCallbackData *)tester->SetUICallback(0,0);
	SCTSASSERT(uiCallbackData);
	uiCallbackData->errorLog=0;
	uiCallbackData->errorLogUI=0;
	tester->SetUICallback(uiCallbackData,uiCallback);
	GetDlgItem(IDC_TESTERRORS)->ShowWindow(SW_HIDE);
	tester->ResetTests();
	/*for (_testInfo=tester->testInfo;_testInfo;_testInfo=_testInfo->next)
	{
		_testInfo->state=_testInfo->state==TEST_OPTIONAL?TEST_OPTIONAL:NOT_TESTED;
		_testInfo->timeStamp=0;
	}*/ 
	tester->SetNextTestGroupID(1);
	Refresh();
}

void CTestPane::OnTestreport() 
{
	CFileDialog fDlg(FALSE,"html",NULL,OFN_HIDEREADONLY,"HTML Files (*.html)|*.html||");
 	fDlg.m_ofn.lpstrTitle="Create Report";
	fDlg.m_ofn.lpstrInitialDir=logPath;
	/* SyncFest #7: Switch directory back to logs */
	if (fDlg.DoModal()==IDCANCEL) 
	{
		SetCurrentDirectory(logPath);
		return;
	}
	SetCurrentDirectory(logPath);
	tester->GenerateReport(fDlg.m_ofn.lpstrFile);
}
