#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/gadtools.h>
#include <dos/dos.h>

#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <string.h>

/* for debug purposes */
#include <stdio.h>

#include "split.h"

extern struct List *vlist;

extern BOOL stay;

extern BOOL setUpGadgets( void );
extern void removeGadgets( void );

extern struct List *getVolumeList( struct List * );
extern void freeVolumeList( struct List * );

extern struct Gadget *glist, *vlist_gad, *chunkoffs_gad,
	*chunknam2_gad, *chunksize_gad;
extern struct VisualInfo *vi;

extern char filename[128];
extern ULONG filesize;
extern STRPTR status_title, msg_ok, msg_warnbadpatch;
extern STRPTR statname[4];
extern UBYTE status;
extern char chunkname[128];
extern UBYTE chunk_number;
extern ULONG chunksize, chunkoffset;
extern void updateGadgets( void );
extern void newChunkList( void );
extern BOOL checkChunk( void );
extern void getNextChunk( void );
extern void goIdle( void );
extern void writeNextChunk( void );

/* in handler.s */
extern BOOL resetDOSlibrary( void );

/* in split.c */
extern int spltype;

extern void askSource( void );
extern void askDest( void );

STRPTR msg_author, msg_cool,
	msg_warnfilenotproc, msg_filenotprocgadgets, msg_filenotprocquitgad,
	msg_warninvalidchunk, msg_invalidchunkgadgets;

#define MENUID_ABOUT 1
#define MENUID_HIDE  2
#define MENUID_QUIT  3
#define MENUID_SPL0  4
#define MENUID_SPL1  5

struct EasyStruct easyr = {
	sizeof(struct EasyStruct), 0, NULL, NULL, NULL };

struct Menu *menus;

struct NewMenu newmenus[] = {
	{ NM_TITLE, NULL,         0, 0, 0, 0 },
	{ NM_ITEM,  NULL,         0, 0, 0, (APTR)MENUID_ABOUT },
	{ NM_ITEM,  NULL,         0, 0, 0, (APTR)MENUID_HIDE },
	{ NM_ITEM,  NULL,	      0, 0, 0, (APTR)MENUID_QUIT },

	{ NM_TITLE, NULL,         0, 0, 0, 0 },
	{ NM_ITEM,  "SPL0",     "0", CHECKIT|MENUTOGGLE, ~1, (APTR)MENUID_SPL0 },
	{ NM_ITEM,  "SPL1",     "1", CHECKIT|MENUTOGGLE|CHECKED, ~2, (APTR)MENUID_SPL1 },
	{ NM_END,   NULL,         0, 0, 0, 0 } };

struct Window *window;
ULONG windowSig;
UWORD wwidth, wheight, wleft = (UWORD)~0, wtop = (UWORD)~0;

void openGUI( void )
{
vlist = getVolumeList( vlist );

if ( window )
	return;

if ( setUpGadgets() )
	{
	if ( window = OpenWindowTags( NULL,
		WA_Left, wleft,
		WA_Top, wtop,
		WA_Width, wwidth,
		WA_Height, wheight,
		WA_Gadgets, glist,
		WA_Title, "Split",
		WA_ScreenTitle, "Split 1.1 © 1995 by Stefano Reksten of 3AM",
		WA_Flags, WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_ACTIVATE,
		WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_GADGETDOWN|IDCMP_REFRESHWINDOW|IDCMP_MENUPICK|LISTVIEWIDCMP,
		TAG_END ) )
		{
		if ( menus = CreateMenus( newmenus, TAG_END ) )
			{
			if ( LayoutMenus( menus, vi, TAG_END ) )
				{
				if ( SetMenuStrip( window, menus ) )
					{
					GT_RefreshWindow( window, NULL );
					ScreenToFront( window->WScreen );
					windowSig = 1L<<window->UserPort->mp_SigBit;
					updateGadgets();
					return;
					}
				}
			FreeMenus( menus );
			}
		CloseWindow( window );
		}
	else
		removeGadgets();
	}
}


void closeGUI( void )
{
if ( window )
	{
	wleft = window->LeftEdge;
	wtop = window->TopEdge;
	CloseWindow( window );
	window = NULL;
	removeGadgets();
	freeVolumeList( vlist );
	vlist = NULL;
	}
}


ULONG sec, mic, oldsec, oldmic;


void quit( void )
{
if ( status != STATUS_IDLE )
	{
	easyr.es_TextFormat = msg_warnfilenotproc;
	easyr.es_GadgetFormat = msg_filenotprocquitgad;
	if ( !EasyRequestArgs( window, &easyr, NULL, NULL ) )
		return;
	}
if ( !resetDOSlibrary() )
	{
	easyr.es_TextFormat = msg_warnbadpatch;
	easyr.es_GadgetFormat = msg_ok;
	EasyRequestArgs( NULL, &easyr, NULL, NULL );
	return;
	}
stay = FALSE;
}


UWORD lastnumber;
void updateVolumeList( UWORD number )
{
if ( window )
	GT_SetGadgetAttrs( vlist_gad, window, NULL, GTLV_Labels, ~0, TAG_END );
vlist = getVolumeList( vlist );
if ( window )
	{
	if ( number != (UWORD)~0 )
		lastnumber = number;
	GT_SetGadgetAttrs( vlist_gad, window, NULL, GTLV_Labels, vlist, GTLV_Selected, lastnumber, TAG_END );
	}
}


ULONG maxChunkSize( UWORD code )
{
register struct volumeInfo *vi =(struct volumeInfo *)vlist->lh_Head;
UBYTE n;
ULONG blkptrPerBlock, freeblocks, fileblocks;

for ( n = 0; n < code; n++ )
	vi = (struct volumeInfo *)vi->volumeNode.ln_Succ;

if ( vi->diskType != ID_MSDOS_DISK )
	{
	blkptrPerBlock = ( vi->diskType == ID_DOS_DISK || vi->diskType == ID_INTER_DOS_DISK || vi->diskType == ID_FASTDIR_DOS_DISK ) ? 72 : (vi->bytesPerBlock >> 2) - 56;
	freeblocks = vi->freeBlocks;
	fileblocks = 0;
	while( freeblocks )
		{
		freeblocks--;
		if ( freeblocks > blkptrPerBlock )
			{
			fileblocks += blkptrPerBlock;
			freeblocks -= blkptrPerBlock;
			}
		else
			{
			fileblocks += freeblocks;
			freeblocks = 0;
			}
		}
	return fileblocks * vi->bytesPerBlock;
	}
else
	return (ULONG)vi->freeSpace;
}


void handleWindowSig( void )
{
register struct IntuiMessage *msg;
register ULONG class, menuid;
register UWORD code, msgID;

while( window && stay && ( msg = GT_GetIMsg(window->UserPort) ) )
	{
	class = msg->Class;
	if (class & (BUTTONIDCMP|IDCMP_GADGETDOWN))
		{
		code = msg->Code;
		msgID = ((struct Gadget *)msg->IAddress)->GadgetID;
		}
	if (class == IDCMP_VANILLAKEY || class == IDCMP_MENUPICK )
		msgID = msg->Code;
	GT_ReplyIMsg( msg );

	switch( class )
		{
		case IDCMP_REFRESHWINDOW:
			GT_BeginRefresh( window );
			GT_EndRefresh( window, TRUE );
			break;

		case IDCMP_MENUPICK:
			if ( msgID != MENUNULL )
				{
				menuid = (ULONG)GTMENUITEM_USERDATA( ItemAddress( menus, msgID ) );
				switch ( menuid )
					{
					case MENUID_ABOUT:
						easyr.es_TextFormat = msg_author;
						easyr.es_GadgetFormat = msg_cool;
						if ( IntuitionBase->LibNode.lib_Version >= 39 )
							SetWindowPointer( window, WA_BusyPointer, TRUE, TAG_END );
						EasyRequestArgs( window, &easyr, NULL, NULL );
						if ( IntuitionBase->LibNode.lib_Version >= 39 )
							SetWindowPointer( window, TAG_END );
						break;
					case MENUID_HIDE:
						closeGUI();
						break;
					case MENUID_QUIT:
						quit();
						break;
					case MENUID_SPL0:
						spltype = SPLTYPE0;
						break;
					case MENUID_SPL1:
						spltype = SPLTYPE1;
						break;
					}
				}
			break;

		case IDCMP_CLOSEWINDOW:
			closeGUI();
			break;

		case BUTTONIDCMP:
		case IDCMP_GADGETDOWN:
			switch ( msgID )
				{
				case DOSLIST_GDG:
					vlist = getVolumeList( vlist );
					updateVolumeList( code );
					oldsec = sec;
					oldmic = mic;
					CurrentTime( &sec, &mic );
					if ( DoubleClick( oldsec, oldmic, sec, mic ) )
						{
						struct volumeInfo *vi =(struct volumeInfo *)vlist->lh_Head;
						UBYTE n;

						chunksize = maxChunkSize( code ) - ( spltype == SPLTYPE0 ? sizeof(struct Header) : sizeof(struct ExtHeader) );
						if ( filesize && ( chunksize + chunkoffset > filesize ) )
								chunksize = filesize - chunkoffset;
						for ( n = 0; n < code; n++ )
							vi = (struct volumeInfo *)vi->volumeNode.ln_Succ;
						strcpy( chunkname, vi->deviceName );
						updateGadgets();
						}
					break;
				case CHUNK_GDG:
					getNextChunk();
					break;
				case CHUNKSIZE_GDG:
					GT_GetGadgetAttrs( chunksize_gad, window, NULL, GTIN_Number, &chunksize, TAG_END );
					if ( filesize && ( chunkoffset + chunksize > filesize ) )
						{
						chunksize = filesize - chunkoffset;
						updateGadgets();
						}
					break;
				case CHUNKOFFS_GDG:
					GT_GetGadgetAttrs( chunkoffs_gad, window, NULL, GTIN_Number, &chunkoffset, TAG_END );
					if ( filesize )
						{
						if ( chunkoffset > filesize )
							chunkoffset = 0;
						else if ( chunkoffset + chunksize > filesize )
							chunksize = filesize - chunkoffset;
						updateGadgets();
						}
					break;
				case WRITE_GDG:
					if ( checkChunk() )
						writeNextChunk();
					else
						{
						easyr.es_TextFormat = msg_warninvalidchunk;
						easyr.es_GadgetFormat = msg_invalidchunkgadgets;
						if ( EasyRequestArgs( window, &easyr, NULL, NULL ) )
							getNextChunk();
						}
					break;
				case CHUNKNAM1_GDG:
					askDest();
					break;
				case CHUNKNAM2_GDG:
					strcpy( chunkname, ((struct StringInfo *)chunknam2_gad->SpecialInfo)->Buffer );
					break;
				case FILENAM1_GDG:
					if ( status != STATUS_IDLE )
						{
						easyr.es_TextFormat = msg_warnfilenotproc;
						easyr.es_GadgetFormat = msg_filenotprocgadgets;
						if ( !EasyRequestArgs( window, &easyr, NULL, NULL ) )
							break;
						else
							goIdle();
						}
					askSource();
					if ( filesize < chunksize + chunkoffset )
						{
						chunksize = filesize - chunkoffset;
						updateGadgets();
						}
					getNextChunk();
					break;
				case HIDE_GDG:
					closeGUI();
					break;
				case QUIT_GDG:
					quit();
					break;
				}
		    break;
		}
	}
}
