/*
Copyright (c) 1998 Richard Lawrence

This program is free software; you can redistribute it and/or modify it under the terms 
of the GNU General Public License as published by the Free Software Foundation; either 
version 2 of the License, or (at your option) any later version. This program is 
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details. You should have received a copy of the GNU
General Public License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

// CDriveDialog.cpp : implementation file
//

#include "stdafx.h"
#include "Atari800Win.h"
#include "CDriveDialog.h"
#include "WinAtari.h"

extern "C" {
#include "registry.h"
#include "sio.h"
extern void WriteAtari800Drives( HKEY hkInput );
extern UnitStatus drive_status[];
extern TCHAR	gcErrorString[];
extern BOOL IsCompressedFile( char *filename );
}

static UnitStatus NewUnitStatus[MAX_DRIVES];


static char new_sio_filename[MAX_DRIVES][MAX_PATH];
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static int nDlgEditID[MAX_DRIVES] =  {IDC_EDIT1, IDC_EDIT2, IDC_EDIT3, IDC_EDIT4, IDC_EDIT5, IDC_EDIT6, IDC_EDIT7, IDC_EDIT8 };
static int nDlgDiskCombo[MAX_DRIVES] = { IDC_DISK1COMBO, IDC_DISK2COMBO, IDC_DISK3COMBO, IDC_DISK4COMBO, IDC_DISK5COMBO, IDC_DISK6COMBO, IDC_DISK7COMBO, IDC_DISK8COMBO };
static int nDriveButtons[MAX_DRIVES] = { IDC_DRIVE1, IDC_DRIVE2, IDC_DRIVE3, IDC_DRIVE4, IDC_DRIVE5, IDC_DRIVE6, IDC_DRIVE7, IDC_DRIVE8 };
/////////////////////////////////////////////////////////////////////////////
// CDriveDialog dialog


CDriveDialog::CDriveDialog(CWnd* pParent /*=NULL*/)
	: CDialog(CDriveDialog::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDriveDialog)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

BEGIN_MESSAGE_MAP(CDriveDialog, CDialog)
	//{{AFX_MSG_MAP(CDriveDialog)
	ON_BN_CLICKED(IDC_CLEAR_DRIVES, OnClearDrives)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDriveDialog message handlers

void CDriveDialog::SetButtons( void )
{
	int i;

	CComboBox	*cbComboBox;
	for( i=0; i < MAX_DRIVES; i++ )
	{
		SetDlgItemText( nDlgEditID[i], new_sio_filename[i] );

		cbComboBox = (CComboBox *)GetDlgItem( nDlgDiskCombo[i] );
		ASSERT( cbComboBox );
		
		switch( NewUnitStatus[i] )
		{
			case Off:
				cbComboBox->SetCurSel( 0 );
				break;

			case NoDisk:
				cbComboBox->SetCurSel( 3 );
				break;

			case ReadOnly:
				cbComboBox->SetCurSel( 2 );
				break;

			case ReadWrite:
				cbComboBox->SetCurSel( 1 );
				break;
		}
	}
}

//We set the drive edit boxes to the the appropriate values, and set the status ListBox
BOOL CDriveDialog::OnInitDialog() 
{
	int i;
	CDialog::OnInitDialog();

	for( i = 0; i < MAX_DRIVES; i++ )
	{
		strcpy( new_sio_filename[i], sio_filename[i] );
		NewUnitStatus[i] = drive_status[i];
	}
	SetButtons();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

//GetDiskImage will call up a file dialog, and if the user oks the file will copy
//it's name into the appropriate edit box. The drives are not unmounted/mounted 
//until the OK button is pushed, in case the user decides to cancel the entire 
//operation. So the edit boxes are being used as temporary buffers, basically
BOOL CDriveDialog::GetDiskImage( int disknum )
{
	CString	name;
	char	szCurDir[ MAX_PATH ];
	char	szPrompt[ 64 ];

	char BASED_CODE szFilter[] = "Atari disk images (*.atr,*.xfd, etc)|*.atr;*.xfd;*.atr.gz;*.atz;*.xfd.gz;*.xfz;*.dcm|ATR Images only (*.atr,*.atr.gz,*.atz)|*.atr;*.atr.gz;*.atz|XFD Images only (*.xfd,*.xfd.gz,*.xfz)|*.xfd;*.xfd.gz;*.xfz|DCM Images only (*.dcm)|*.dcm|All Files (*.*)|*.*||";
	CFileDialog	dlgDiskImage( TRUE, NULL, NULL, OFN_EXPLORER | OFN_FILEMUSTEXIST, szFilter, this );

	sprintf( szPrompt, "Select disk for drive %d", disknum + 1);
	dlgDiskImage.m_ofn.lpstrTitle = szPrompt;
	GetCurrentDirectory( MAX_PATH, szCurDir );
	if( strcmp( new_sio_filename[ disknum ], "Empty" ) && strcmp( new_sio_filename[ disknum ], "None" ) &&
		strcmp( new_sio_filename[ disknum ], "Off" ) )
	{
		char	szNewDir[ MAX_PATH ];
		int i;

		ReadRegBinary( NULL, szDriveRegID[ disknum ], &szNewDir[0], MAX_PATH, FALSE );
		for( i=strlen( szNewDir ); i > 0 && szNewDir[i]!='\\'; i--);
		if( i > 0 )
			szNewDir[i] = 0;
		SetCurrentDirectory( szNewDir );
	}

	if( dlgDiskImage.DoModal() == IDOK )
	{
		name = dlgDiskImage.GetPathName();
		SetDlgItemText( nDlgEditID[disknum], name.GetBuffer(0) );
		strcpy( new_sio_filename[disknum], name.GetBuffer(0) );
		name.ReleaseBuffer();
		
		CFile cfile( new_sio_filename[disknum], CFile::modeReadWrite );
		if( !cfile.m_hFile )
			NewUnitStatus[ disknum ] = ReadOnly;
		else
			NewUnitStatus[ disknum ] = ReadWrite;
		cfile.Close();
		
		if( IsCompressedFile( new_sio_filename[disknum] ) )
			NewUnitStatus[ disknum ] = ReadOnly;

		return TRUE;
	}
	SetCurrentDirectory( szCurDir );

	return FALSE;
}

bool CDriveDialog::DriveButton( int nButtonID, HWND hwndButton )
{
	int i, nDriveID = -1;

	for( i=0; i < MAX_DRIVES; i++ )
	{
		if( nButtonID == nDriveButtons[i] ) 
			nDriveID = i;
	}
	
	if( nDriveID == -1 )	//It wasn't a drive button
		return false;

	if( GetDiskImage( nDriveID ) )
	{
		SetButtons();
	}

	return true;
}

void CDriveDialog::StatusSelChange( int nComboID, HWND hwndComboBox )
{
	int i, nDriveID = -1;
	CComboBox	*comboBox = NULL;
	ASSERT( comboBox );
	
	for( i=0; i < MAX_DRIVES; i++ )
	{
		if( nComboID == nDlgDiskCombo[i] ) 
			nDriveID = i;
	}
	
	if( nDriveID == -1 )	//It wasn't a drive button
		return;

	comboBox = (CComboBox *)GetDlgItem( nDlgDiskCombo[nDriveID] );
	switch( comboBox->GetCurSel() )
	{
		case 0:	//Combo box indicates "Off"
		{
			NewUnitStatus[ nDriveID ] = Off;
			strcpy( new_sio_filename[ nDriveID ], "Off" );
			break;
		}
		case 1: //Combo box indicates "Read/Write"
		{
			UnitStatus	NewMode = Off;

			if( NewUnitStatus[ nDriveID ] == Off || NewUnitStatus[ nDriveID] == NoDisk )
				NewMode = NewUnitStatus[ nDriveID ];
			else if( NewUnitStatus[ nDriveID ] == ReadWrite )
				NewMode = ReadWrite;
			else
			{
				if( IsCompressedFile( new_sio_filename[ nDriveID ] ) )
				{
					MessageBox( "Cannot write to a compressed disk image, mode remains Read Only", "Atari800Win", MB_OK );
					NewMode = ReadOnly;
				}
				else
				{
					//Yes, I know this can be tested with an exception throw. It's a lot more wordy to write out
					//however. Just open the file and see if we got a handle to see if it supports ReadWrite
					CFile cfile( new_sio_filename[ nDriveID ], CFile::modeReadWrite );
					if( !cfile.m_hFile )
					{
						NewMode = ReadOnly;
						MessageBox( "Could not set to Read/Write because the file is marked Read Only or unavailable", "Atari800Win", MB_OK );
					}
					else
						NewMode = ReadWrite;
					cfile.Close();
				}

				NewUnitStatus[nDriveID] = NewMode;
				SetButtons();
			}
		}
		case 2:	//Combo box indicates "Read Only"
		{
			if( NewUnitStatus[ nDriveID ] == ReadOnly || NewUnitStatus[ nDriveID ] == ReadWrite )
				NewUnitStatus[ nDriveID ] = ReadOnly;
		}
		case 3: //Combo box indicates "No Disk"
		{
			NewUnitStatus[ nDriveID ] = NoDisk;
		}
		default:;
	}
}

//The reason for doing this here instead of just doing it in GetDiskImage is
//to preserve the ability to cancel the entire drive operation with one
//click of the cancel button.
void CDriveDialog::OnOK() 
{
	int i;
	char	szFileName [ MAX_PATH ];
	BOOL	bDrivesChanged = FALSE;

	CDialog::OnOK();

	for( i = 0; i < MAX_DRIVES; i++ )
	{
		GetDlgItemText( nDlgEditID[i], szFileName, MAX_PATH );
		if( NewUnitStatus[ i ] == Off )
			strcpy( szFileName, "Off" );
		if( NewUnitStatus[ i ] == NoDisk )
			strcpy( szFileName, "Empty" );

		if( NewUnitStatus[ i ] != drive_status[ i ] )
			bDrivesChanged = TRUE;

		if( strcmp( szFileName, sio_filename[i] ) )
		{
			bDrivesChanged = TRUE;
			strcpy( sio_filename[i], szFileName );
			if( !strcmp( szFileName, "Empty" ) )
				SIO_Dismount( i + 1 );
			else
			{
				SIO_Dismount( i + 1 );
				SIO_Mount( i + 1, szFileName );		
			}
		}

		drive_status[ i ] = NewUnitStatus[ i ];
	}

	if( bDrivesChanged )
		WriteAtari800Drives( NULL );
}


void CDriveDialog::OnClearDrives() 
{
	int i;

	for( i=0; i < MAX_DRIVES; i++ )
	{
		NewUnitStatus[ i ] = Off;
		memset( new_sio_filename[i], 0, MAX_PATH );
		strcpy( new_sio_filename[i], "Off" );
	}
	SetButtons();
}

//This could also be handled by eight OnSelChanged plus eight ButtonClicked individual 
//procedures, but this seems a little more elegant
BOOL CDriveDialog::OnCommand(WPARAM wParam, LPARAM lParam) 
{
	switch( HIWORD( wParam ) )
	{
		case	CBN_SELCHANGE:
			{
				StatusSelChange( (int)LOWORD(wParam), (HWND)lParam );
				return TRUE;
				break;
			}

		case	BN_CLICKED:
			{
				if( DriveButton( (int)LOWORD(wParam), (HWND)lParam ) )
					return TRUE;
				break;
			}
		default:;
	}
	
	return CDialog::OnCommand(wParam, lParam);
}
