//    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
//    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., 675 Mass Ave, Cambridge, MA 02139, USA.
//

#include "pub.def"
#include "jintypes.h"
#include "autil.h"
#include "adsk.h"

BOOL Convert( char* szInFile, char* szOutFile );

DISK_TYPE g_dtypeIn = DISK_AUTO;
DISK_TYPE g_dtypeOut = DISK_ATR;

BOOL g_bVerbose = FALSE;
BOOL g_bBatchMode = FALSE;
BOOL g_bRepairAuto = FALSE;
BOOL g_bRepair = TRUE;
BOOL g_bFirstErrStop = FALSE;
BOOL g_bOverWrite = FALSE;
BOOL g_bTestOnly = FALSE;
BOOL g_bForceClassic = FALSE;

#define SHEADER PRG_NAME " v" PRG_VERSION " (c) " PRG_COPYRIGHT " " PRG_AUTHOR "\n"

#define HEADER SHEADER \
   PRG_DESC "\n" \
	"  Latest version can be found at " PRG_URL "\n" \
	"  Published under GPL. See GPL.TXT.\n\n"

#define USAGE HEADER "Usage:  " PRG_NAME " " PRG_USAGE

#include "switches.cpp"

int main(int argc,char *argv[])
{
	setbuf( stdout, NULL );
	setbuf( stderr, NULL );

	if ( !SWITCHES_Init( &argc, argv ) )
		return 1;

	if ( argc < 2 )
	{
		SWFN_HELP( USAGE );
		return 1;
	}

	fprintf( stderr, SHEADER );

	BOOL bRet = FALSE;

	char szOutFile[ 255 ];

	if ( g_bBatchMode )
	{
		argc--;
		argv++;

		while( argc-- )
		{
			char* szInFile = *(argv++);
			GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) );
			bRet = Convert( szInFile, szOutFile );
			printf( "\n" );

			if ( !bRet && g_bFirstErrStop )
				break;
		}

	}
	else
	{
		char* szInFile = argv[ 1 ];

		if ( argc >= 3 )
		{
			strcpy( szOutFile, argv[ 2 ] );
		}
		else
		{
			GuessBestFnameFromPC( szOutFile, szInFile, GetDiskTypeExt( g_dtypeOut ) );
		}

		bRet = Convert( szInFile, szOutFile );
	}

	if ( bRet && !g_bTestOnly )
		printf ( "Done.\n" );

	return bRet ? 0 : 1;
}

BOOL Convert( char* szInFile, char* szOutFile )
{
	ADisk* pDiskIn = NULL;
	ADisk* pDiskOut = NULL;

	DISKINIT_RETCODE ret;

	g_dtypeIn = DISK_ATR;
	if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_ATR, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) )
	{
		g_dtypeIn = DISK_DI;
		if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_DI, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) )
		{
			g_dtypeIn = DISK_DCM;
			if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_DCM, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) )
			{
				g_dtypeIn = DISK_SCP;
				if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_SCP, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) )
				{
					g_dtypeIn = DISK_XFD;
					if ( DI_RET_CONTINUE == ( ret = InitializeDisk( &pDiskIn, DISK_XFD, szInFile, FALSE, g_bRepair, g_bRepairAuto ) ) )
					{
						printf( "Unable to determine format of disk image '%s'!\n", szInFile );
						return FALSE;
					}
				}
			}
		}
	}

	if ( ret == DI_RET_CANT_CONTINUE )
		return FALSE;

	printf( "Input file '%s' (%s)\n", szInFile, GetDiskTypeName( g_dtypeIn ) );

	if ( g_bVerbose )
	{
		DISK_GEOMETRY* pgeo = pDiskIn->GetGeometry();
		printf( "Sides: %d\n", pgeo->iSides );
		printf( "Tracks: %d\n", pgeo->iTracks );
		printf( "SecPerTrack: %d\n", pgeo->iSectorsPerTrack );
		printf( "BytesPerSec: %d\n", pgeo->iBytesPerSector );
		printf( "Sectors: %d\n", pgeo->iSectors );
	}

	if ( g_bTestOnly )
	{
		printf( "File loaded OK.\n" );
		delete pDiskIn;
		return TRUE;
	}

	switch( g_dtypeOut )
	{
		case DISK_ATR:
			pDiskOut = new CAtr();
			break;

		case DISK_XFD:
			pDiskOut = new CXfd();
			break;

		case DISK_DI:
			pDiskOut = new CDi();
			break;

		case DISK_SCP:
			pDiskOut = new CScp();
			break;

		case DISK_DCM:
			pDiskOut = new CDcm();
			break;

		default:
			break;
	}

	if ( !pDiskOut )
	{
		fprintf( stderr, "Can't create such image!\n" );
		return FALSE;
	}

	DISK_GEOMETRY* pgeo = pDiskIn->GetGeometry();
	DISK_GEOMETRY forced;

	memcpy( &forced, pgeo, sizeof( DISK_GEOMETRY ) );

	if ( g_bForceClassic )
		ForceClassicSize( &forced );

	//duplicating the image
	pDiskOut->Duplicate( pDiskIn, &forced );

	printf( "Output file '%s' (%s)\n", szOutFile, GetDiskTypeName( g_dtypeOut ) );

	//and save it in new format
	if ( !pDiskOut->Save( szOutFile, g_bOverWrite ) )
	{
		printf( "Error! %s\n", pDiskOut->GetLastError() );
		delete pDiskIn;
		delete pDiskOut;
		return FALSE;
	}

	delete pDiskIn;
	delete pDiskOut;

	return TRUE;
}