/**********************************************************************/
/**                       Microsoft Windows/NT                       **/
/**                Copyright(c) Microsoft Corporation, 1997 - 1998 **/
/**********************************************************************/

/*
    busydlg.cpp
	base class for the busy dialog

    FILE HISTORY:
	
*/

#include "stdafx.h"
#include "busydlg.h"

/////////////////////////////////////////////////////////////////////////////
// CWorkerThread

CWorkerThread::CWorkerThread()
{
	m_bAutoDelete = FALSE;
	m_bAbandoned = FALSE;
	m_hEventHandle = NULL;
	::InitializeCriticalSection(&m_cs);
	m_hWnd = NULL; 
}

CWorkerThread::~CWorkerThread()
{
	::DeleteCriticalSection(&m_cs);
	if (m_hEventHandle != NULL)
	{
		VERIFY(::CloseHandle(m_hEventHandle));
		m_hEventHandle = NULL;
	}
}

BOOL CWorkerThread::Start(HWND hWnd)
{
	ASSERT(m_hWnd == NULL);
	ASSERT(::IsWindow(hWnd));
	m_hWnd = hWnd;

	ASSERT(m_hEventHandle == NULL); // cannot call start twice or reuse the same C++ object
	m_hEventHandle = ::CreateEvent(NULL,TRUE /*bManualReset*/,FALSE /*signalled*/, NULL);
	if (m_hEventHandle == NULL)
		return FALSE;
	return CreateThread();
}

void CWorkerThread::Abandon()
{
	Lock();
	OnAbandon();
	m_bAutoDelete = TRUE;
	m_bAbandoned = TRUE;
	Unlock();
}


BOOL CWorkerThread::IsAbandoned()
{
	Lock();
	BOOL b = m_bAbandoned;
	Unlock();
	return b;
}

BOOL CWorkerThread::PostMessageToWnd(UINT Msg, WPARAM wParam, LPARAM lParam)
{
	BOOL b = IsAbandoned();
	if (b)
		return TRUE; // no need to post
	ASSERT(::IsWindow(m_hWnd));
	return ::PostMessage(m_hWnd, Msg, wParam, lParam);
}

void CWorkerThread::WaitForExitAcknowledge() 
{
	BOOL b = IsAbandoned();
	if (b)
		return;
	VERIFY(WAIT_OBJECT_0 == ::WaitForSingleObject(m_hEventHandle,INFINITE)); 
}

/////////////////////////////////////////////////////////////////////////////
// CDlgWorkerThread

CDlgWorkerThread::CDlgWorkerThread()
{
	m_dwErr = 0x0;
}


BOOL CDlgWorkerThread::Start(CLongOperationDialog* pDlg)
{
	ASSERT(pDlg != NULL);
	HWND hWnd = pDlg->GetSafeHwnd();
	return CWorkerThread::Start(hWnd);
}

BOOL CDlgWorkerThread::PostMessageToDlg()
{
	return PostMessageToWnd(CLongOperationDialog::s_nNotificationMessage,
							(WPARAM)0, (LPARAM)0);
}


int CDlgWorkerThread::Run()
{
	// do the stuff
	OnDoAction();
	VERIFY(PostMessageToDlg());
	WaitForExitAcknowledge();
	//TRACE(_T("exiting\n"));
	return 0;

}


/////////////////////////////////////////////////////////////////////////////
// CLongOperationDialog dialog

UINT CLongOperationDialog::s_nNotificationMessage = WM_USER + 100;

CLongOperationDialog::CLongOperationDialog(CDlgWorkerThread* pThreadObj,
										   UINT nAviID)
	: CDialog(IDD_BUSY, NULL),
      m_bCancel(TRUE)
{
	ASSERT(pThreadObj != NULL);
	m_bAbandoned = TRUE;
	m_pThreadObj = pThreadObj;
	m_nAviID = nAviID;
}

CLongOperationDialog::~CLongOperationDialog()
{
	if(m_pThreadObj != NULL)
	{
		delete m_pThreadObj;
		m_pThreadObj = NULL;
	}
}

BOOL CLongOperationDialog::LoadTitleString(UINT nID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return m_strTitle.LoadString(nID);
}

BOOL CLongOperationDialog::LoadDescriptionString(UINT nID)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return m_strDescription.LoadString(nID);
}

BEGIN_MESSAGE_MAP(CLongOperationDialog, CDialog)
	ON_MESSAGE( CLongOperationDialog::s_nNotificationMessage, OnNotificationMessage )
END_MESSAGE_MAP()


afx_msg LONG CLongOperationDialog::OnNotificationMessage( WPARAM wParam, LPARAM lParam)
{
	TRACE(_T("CLongOperationDialog::OnNotificationMessage()\n"));

	ASSERT(m_pThreadObj != NULL);
	if (m_pThreadObj != NULL)
	{
		m_pThreadObj->AcknowledgeExiting();
		VERIFY(WAIT_OBJECT_0 == ::WaitForSingleObject(m_pThreadObj->m_hThread,INFINITE));
		m_bAbandoned = FALSE;
		PostMessage(WM_CLOSE,0,0);
	}
	return 0;
}

BOOL CLongOperationDialog::OnInitDialog() 
{
	TRACE(_T("CLongOperationDialog::OnInitDialog()\n"));

	CDialog::OnInitDialog();
	
	if (!m_strTitle.IsEmpty())
		SetWindowText(m_strTitle);

	if (!m_strDescription.IsEmpty())
		GetDlgItem(IDC_STATIC_DESCRIPTION)->SetWindowText(m_strDescription);

    // load auto play AVI file if needed
	if (m_nAviID != -1)
	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState());
		CAnimateCtrl* pAnimate = (CAnimateCtrl*)GetDlgItem(IDC_SEARCH_ANIMATE);
		VERIFY(pAnimate->Open(m_nAviID)); 
	}
	
    if (!m_bCancel)
    {
        // hide the system menu
        DWORD dwWindowStyle = GetWindowLong(GetSafeHwnd(), GWL_STYLE);
        dwWindowStyle &= ~WS_SYSMENU;

        SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwWindowStyle);

        // hide the cancel button
        GetDlgItem(IDCANCEL)->ShowWindow(FALSE);
    }

    // spawn worker thread
	GetThreadObj()->Start(this);
	
	return TRUE;
}

void CLongOperationDialog::OnCancel() 
{
	TRACE(_T("CLongOperationDialog::OnCancel()\n"));
	if (m_bAbandoned)
	{
		m_pThreadObj->Abandon();
		m_pThreadObj = NULL;
	}
	CDialog::OnCancel();
}