// PanelLevels.cpp : implementation file
//

#include "stdafx.h"
#include "binarytool.h"
#include "PanelLevels.h"
#include "GlobalData.h"
#include "Scripts.h"
#include "util.h"
#include "Threads.h"
#include "Process.h"
#include "Tasks.h"

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

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// CPanelLevels dialog


CPanelLevels::CPanelLevels(CWnd* pParent /*=NULL*/)
	: CPanel(CPanelLevels::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPanelLevels)
	//}}AFX_DATA_INIT

	_tcscpy( m_szTitle, _T("Binarization") );
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void CPanelLevels::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPanelLevels)
	DDX_Control(pDX, IDC_CHECK_AutoTest, m_CheckAutoTest);
	DDX_Control(pDX, IDC_CHECK_StopOnError, m_CheckStopOnError);
	DDX_Control(pDX, IDC_LIST_Levels, m_ListLevels);
	//}}AFX_DATA_MAP
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

BEGIN_MESSAGE_MAP(CPanelLevels, CDialog)
	//{{AFX_MSG_MAP(CPanelLevels)
	ON_WM_DRAWITEM()
	ON_BN_CLICKED(IDC_BUTTON_SelectAll, OnSelectAllLevels)
	ON_BN_CLICKED(IDC_BUTTON_ClearAll, OnClearAllLevels)
	ON_BN_CLICKED(IDC_BUTTON_Binarize, OnBinarize)
	ON_BN_CLICKED(IDC_CHECK_AutoTest, OnCHECKAutoTest)
	ON_BN_CLICKED(IDC_BUTTON_TestMaps, OnTestMaps)
	ON_BN_CLICKED(IDC_BUTTON_Refresh, OnBUTTONRefreshLevelList)
	ON_BN_CLICKED(IDC_CHECK_StopOnError, OnCHECKStopOnError)
	ON_BN_CLICKED(IDC_BUTTON_EditGameDsc, OnBUTTONEditGameDsc)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

BOOL CPanelLevels::Create( CWnd* pParentWnd )
{
	BOOL bResult = CDialog::Create( IDD, pParentWnd );

	if( bResult )
	{
		// Init bitmap
		m_oCrossDC.CreateCompatibleDC( NULL );
		m_oCrossBitmap.LoadBitmap( IDB_BITMAP_CHECK );
		m_oEmptyBoxBitmap.LoadBitmap( IDB_BITMAP_VIDE );

		// Read registry, update controls
		CWinApp *p_oApp = AfxGetApp();
		CString csSection = m_szTitle;

		m_CheckAutoTest.SetCheck( p_oApp -> GetProfileInt( csSection, _T("AutoTest"), 0 ) );
		g_stTheGlobalData.bAutoTestMaps = m_CheckAutoTest.GetCheck();
		m_CheckStopOnError.SetCheck( p_oApp -> GetProfileInt( csSection, _T("StopOnError"), 1 ) );
		OnCHECKStopOnError();
	}

	return bResult;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::m_fn_vUpdateRegistry()
{
	CWinApp *p_oApp = AfxGetApp();
	CString csSection = m_szTitle;

	p_oApp -> WriteProfileInt( csSection, _T("AutoTest"), m_CheckAutoTest.GetCheck() );
	p_oApp -> WriteProfileInt( csSection, _T("StopOnError"), m_CheckStopOnError.GetCheck() );
}

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// CPanelLevels message handlers


void CPanelLevels::OnOk()
{
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

BOOL CPanelLevels::PreTranslateMessage(MSG* pMsg) 
{
	if( pMsg->hwnd == m_ListLevels.m_hWnd )
	{
			switch ( pMsg->message )
			{
			case WM_LBUTTONDOWN:
					if( m_fn_bOnLButtonDownListBoxLevels( pMsg ) ) return TRUE;
					break;
			case WM_KEYDOWN:
					if( m_fn_bOnKeyDownListBoxLevels( pMsg ) ) return TRUE;
					break;
			default:
					break;
			}
	}

	if( pMsg->message == WM_KEYDOWN && (int)pMsg -> wParam == VK_RETURN )
	{
		OnBinarize();
		return TRUE;
	}

	
	return CDialog::PreTranslateMessage(pMsg);
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	if( nIDCtl == IDC_LIST_Levels )
		m_fn_vOnDrawItemListBoxLevels( lpDrawItemStruct );
	else
		CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::OnSelectAllLevels() 
{
	int iNb = m_ListLevels.GetCount();

	for( int i=0; i<iNb; i++ )
	{
		g_stTheGlobalData.a_cLevelsSelectedForBinarization.SetAt( i, 1 );
	}
	m_ListLevels.Invalidate( FALSE );
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::OnClearAllLevels() 
{
	int iNb = m_ListLevels.GetCount();

	for( int i=0; i<iNb; i++ )
	{
		g_stTheGlobalData.a_cLevelsSelectedForBinarization.SetAt( i, 0 );
	}
	m_ListLevels.Invalidate( FALSE );
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void CPanelLevels::OnBinarize() 
{
	// Count the number of selected levels
	BOOL bAtLeastOneLevel = FALSE;
	int iNb = m_ListLevels.GetCount();

	for( int i=0; i<iNb; i++ )
	{
		if( g_stTheGlobalData.a_cLevelsSelectedForBinarization[i] )
		{
			bAtLeastOneLevel = TRUE;
			break;
		}
	}

	if( bAtLeastOneLevel )
	{

		// Display result panel, button stop, etc...
		g_stTheGlobalData.p_oMainDlg -> m_fn_vNotifyStartOfWork();

		// Start binarization
		if( fn_e_TASK_Binarize( g_stTheGlobalData.a_cLevelsSelectedForBinarization ) == STATUS_C_OK )
			// Then, if we must test the maps, test them.
			if( g_stTheGlobalData.bAutoTestMaps )
			{
				fn_e_TASK_TestBinarizedMaps( g_stTheGlobalData.a_cBinarizedLevels );
			}

		// For binarization of levels, always keep the result screen displayed.
		g_stTheGlobalData.p_oMainDlg -> m_fn_vNotifyEndOfWork( TRUE );
	}
	else
	{
		AfxMessageBox( "Please select at least one level to binarize.", MB_OK | MB_ICONSTOP );
	}
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// CPanelLevels user methods



// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void CPanelLevels::m_fn_vLevelListHasChanged( BOOL _bErrorWhileReadingGameDsc )
{
	m_ListLevels.ResetContent();
	if( ! _bErrorWhileReadingGameDsc )
	{
		int iSize = g_stTheGlobalData.a_csLevelNames.GetSize();
		for( int i=0; i<iSize; i++ )
		{
			m_ListLevels.AddString( g_stTheGlobalData.a_csLevelNames[i] );
		}
	}
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


BOOL CPanelLevels::m_fn_bOnKeyDownListBoxLevels( MSG *pMsg )
{
	return FALSE;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


BOOL CPanelLevels::m_fn_bOnLButtonDownListBoxLevels( MSG *pMsg )
{
	POINT       xPos;
	CRect       oRect;
	BOOL        bOutside;
	int         iIndex;
	CUIntArray  oSelectedItems;
	UINT        uiNbSelectedItems;
	BOOL        bSelect;
	
	// Get the x and y coordinates
	xPos.x = LOWORD( pMsg->lParam );
	xPos.y = HIWORD( pMsg->lParam );
	
	// Determine the object under the cursor in front of which the user clicked
	iIndex = m_ListLevels.ItemFromPoint( xPos, bOutside );

	if( bOutside )
		return FALSE;

	m_ListLevels.GetItemRect ( iIndex , &oRect );
	if( (oRect.PtInRect( xPos )) && (xPos.x < 16) )
	{
		oSelectedItems.SetSize( m_ListLevels.GetCount() );

		// Get list of selected items
		uiNbSelectedItems = m_ListLevels.GetSelItems( m_ListLevels.GetCount(), (int *)oSelectedItems.GetData() );

		// Determine if we must select or deselect the items.
		bSelect = ( g_stTheGlobalData.a_cLevelsSelectedForBinarization.GetAt( iIndex ) == 0);

		BOOL bClickedItemIsSelected = FALSE;
		for( UINT i=0; i<uiNbSelectedItems; i++ )
			if( oSelectedItems[i] == (BYTE)iIndex )
			{
				bClickedItemIsSelected = TRUE;
				break;
			}

		if( bClickedItemIsSelected )
		{
			// Select or deselect the items.
			// Note: the cross in front of the item will be drawn by OnDrawItem
			for( UINT i=0; i<uiNbSelectedItems; i++ )
			{
				g_stTheGlobalData.a_cLevelsSelectedForBinarization.SetAt( oSelectedItems.GetAt(i), (BYTE)bSelect );
			}
		}
		else
		{
			g_stTheGlobalData.a_cLevelsSelectedForBinarization.SetAt( iIndex, (BYTE)bSelect );
		}
		m_ListLevels.Invalidate( FALSE );

		return TRUE;
	}

	return FALSE;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::m_fn_vOnDrawItemListBoxLevels( LPDRAWITEMSTRUCT lpDIS )
{
	CDC                 *pDC = CDC::FromHandle( lpDIS->hDC );
	BOOL                bSelected = (lpDIS->itemState & ODS_SELECTED );
	CString             csItem;
	
	pDC->FillSolidRect( &lpDIS->rcItem, GetSysColor( COLOR_WINDOW ));

	if( lpDIS->itemID < (UINT)m_ListLevels.GetCount() )
	{
		m_ListLevels.GetText( lpDIS->itemID, csItem );
		
		
		// if item is selected, draw a cross, else draw an empty box
		if( g_stTheGlobalData.a_cLevelsSelectedForBinarization[lpDIS->itemID] )
			m_oCrossDC.SelectObject( m_oCrossBitmap );
		else
			m_oCrossDC.SelectObject( m_oEmptyBoxBitmap );

		pDC->BitBlt( lpDIS->rcItem.left + 2, lpDIS->rcItem.top + 1, 12, 12, &m_oCrossDC, 0, 0, SRCAND );

		pDC->SetBkMode( TRANSPARENT);
		pDC->SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
		
		lpDIS->rcItem.left += 16;
		pDC->DrawText( csItem, &lpDIS->rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER );

		// Invert item if selected
		if (bSelected)
		{
			lpDIS->rcItem.left -= 1;
			pDC->InvertRect( &lpDIS->rcItem );
		}
	}
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::OnCHECKAutoTest() 
{
	g_stTheGlobalData.bAutoTestMaps = m_CheckAutoTest.GetCheck();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void CPanelLevels::OnCHECKStopOnError() 
{
	g_stTheGlobalData.bStopBinarizeOnError = m_CheckStopOnError.GetCheck();

	// If user wants the binarization to continue on error, we need to detect errors !
	if( ! g_stTheGlobalData.bStopBinarizeOnError )
	{
		g_stTheGlobalData.bAutoDetectErrors = TRUE;
	}
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 


void CPanelLevels::OnBUTTONRefreshLevelList() 
{
	g_stTheGlobalData.p_oMainDlg -> m_fn_bRefreshLevelList();
}



// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

void CPanelLevels::OnTestMaps() 
{
	BOOL bAtLeastOneLevel = FALSE;
	int iNb = m_ListLevels.GetCount();

	for( int i=0; i<iNb; i++ )
	{
		if( g_stTheGlobalData.a_cLevelsSelectedForBinarization[i] )
		{
			bAtLeastOneLevel = TRUE;
			break;
		}
	}

	if( bAtLeastOneLevel )
	{

		// Display result panel, button stop, etc...
		g_stTheGlobalData.p_oMainDlg -> m_fn_vNotifyStartOfWork();

		// Start test
		fn_e_TASK_TestBinarizedMaps( g_stTheGlobalData.a_cLevelsSelectedForBinarization );

		// For test on levels, always keep the result screen displayed.
		g_stTheGlobalData.p_oMainDlg -> m_fn_vNotifyEndOfWork( TRUE );
	}
	else
	{
		AfxMessageBox( "Please select at least one level to test.", MB_OK | MB_ICONSTOP );
	}
}




void CPanelLevels::OnBUTTONEditGameDsc() 
{
	PROCESS_INFORMATION stProcess;
	char szExeName[512], szCommandLine[512];
	UINT uiLength;

	uiLength = GetSystemDirectory( szExeName, 512 );
	if( uiLength == 0 )
	{
		AfxMessageBox( "Can't get system directory !!.", MB_OK | MB_ICONSTOP );
		return;
	}

	if( szExeName[uiLength-1] != '\\' )
	{
		szExeName[uiLength++] = '\\';
		szExeName[uiLength++] = 0;
	}
	strcpy( &szExeName[uiLength-1], "notepad.exe" );

	sprintf( szCommandLine, "notepad.exe %s\\Gamedata\\Game.dsc", (LPCTSTR)g_stTheGlobalData.csMainDirectory );
	fn_bSpawnProcess( szExeName, szCommandLine, &stProcess );
	fn_vCloseProcessHandles( &stProcess );
}
