/********************************************************************************/
/*								APPLE-EVENT-Basic Command 						*/
/********************************************************************************/

#include "ZipGUI.h"
#include "pathname.h"
#include "helpers.h"
#include "macstuff.h"
#include <stdlib.h>

char *FindNewExtractFolder(char *ArchivePath);

/********************************************************************************/
/*	Global Vars																	*/
/********************************************************************************/

extern ZipGUI_Globals	g;
Boolean ApplescriptQuitWasCalled = false;

pascal OSErr  MyHandleCMDLine (AppleEvent *theAppleEvent, AppleEvent* reply, long
														handlerRefCon);
Boolean isZipFile(FSSpec *fileToOpen);
char *MakeCMDforZip(FSSpec *fileToOpen, long numDocs, char *PathOfDroppedItem);
char *MakeCMDforUnzip(char *archive_path);

int macgetch(void);
char *getenv(const char *name);


#define	kCMDEventClass	'DCMD'
#define	kCMDEvent    	'DCMD'

/********************************************************************************/
/*	Install the Handler for the APPLE-EVENT-Basic Commands	 					*/
/********************************************************************************/

void DoInstallAEHandlers( void )
{
	OSErr	myErr = noErr;

/* install Handler for Open-Application-Event ('oapp')  */
	myErr = AEInstallEventHandler( kCoreEventClass, kAEOpenApplication,
					NewAEEventHandlerProc( DoOAppAE ), 0, false );
	if ( !myErr )
/* install Handler for Open-Documents-Event ('odoc') */
		myErr = AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments,
					NewAEEventHandlerProc( DoODocAE ), 0, false );
	if ( !myErr )
/* install Handler for Print-Documents-Event ('pdoc') */
		myErr = AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments,
					NewAEEventHandlerProc( DoPrintAE ), 0, false );
	if ( !myErr )
/* install Handler for Quit-Application-Event ('quit')   */
		myErr = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication,
					NewAEEventHandlerProc( DoQuitAE ), 0, false );
					
	if ( !myErr )
/* install Handler for CFommandline-Application-Event ('do_CMD')   */
	    myErr = AEInstallEventHandler(kCMDEventClass,kCMDEvent,
					NewAEEventHandlerProc( MyHandleCMDLine ), 0, false );

	if ( myErr )
		DoAlertUser( eNoAppleEvents, true );
} /* DoInstallAEHandlers */


/********************************************************************************/
/*	Process HighLevel-Event   													*/
/********************************************************************************/

void DoHighLevelEvent( EventRecord *myEvent )
{
	OSErr myErr = noErr;
	
	myErr = AEProcessAppleEvent( myEvent );
	if ( myErr )
		SysBeep( 30 );
		
	if (ApplescriptQuitWasCalled == true)
		DoQuit();
		
} /* DoHighLevelEvent */


/********************************************************************************/
/*	Open-Application-Event 														*/
/********************************************************************************/

pascal OSErr DoOAppAE( AppleEvent *myAppleEvent, AppleEvent *myReply, long refCon )
{
myAppleEvent = myAppleEvent;
myReply = myReply;
refCon = refCon;

/* create new Documentwindow */
/*	DoNew(MessageWindow);  */  /* normally an App should open a window at startup
								but to allow a quiet operation the window will be
								open only if there is a printout  */
	return noErr;	
} /* DoOAppAE */


/********************************************************************************/
/*	Open-Documents-Event 														*/
/********************************************************************************/

pascal OSErr DoODocAE( AppleEvent *myAppleEvent, AppleEvent *myReply, long refCon )
{
	long		numDocs, docCount, actualSize;
	FSSpec		fileToOpen;
	AEDescList	myDocList;
	AEKeyword	ignoreKeyword;
	DescType	ignoreType;
	OSErr		myErr = noErr, ZipErr = -1;
	WindowRef	myWindow = nil;
	char 		*CommandLine;
	Boolean     IsZipFile = false;
	char		*PathOfDroppedItem;

myAppleEvent = myAppleEvent;
myReply = myReply;
refCon = refCon;
g.PathAreOK = true;



    /* get the list of all files to open */
	myErr = AEGetParamDesc( myAppleEvent, keyDirectObject, typeAEList, &myDocList );
	if ( myErr )
		return myErr;

	myErr = MyGotRequiredParams( myAppleEvent );
	if ( myErr )
		return myErr;
	
	/* count of the files */
	myErr = AECountItems( &myDocList, &numDocs );
	if ( myErr )
		return myErr;

	PathOfDroppedItem = StrCalloc(NAME_MAX);

	for ( docCount = 1; docCount <= numDocs; docCount++) {		
	/* get FSSpec of the file */
		myErr = AEGetNthPtr( &myDocList, docCount, typeFSS, &ignoreKeyword, 
				&ignoreType, (Ptr)&fileToOpen, sizeof( FSSpec ), &actualSize );
		if ( myErr )
			return myErr;
			
		IsZipFile = isZipFile(&fileToOpen);
		
		GetFullPathFromSpec(PathOfDroppedItem, &fileToOpen , &myErr);

		if (CheckMountedVolumes(PathOfDroppedItem) > 1)
			{
			DoWarnUserDupVol(PathOfDroppedItem);
			AEDisposeDesc( &myDocList );
			return myErr;
			}

		if (!IsZipFile) 
			{  
			CommandLine = MakeCMDforZip(&fileToOpen, numDocs,PathOfDroppedItem);
			if (CommandLine == NULL)
				return false;		
			} 
		else 
			{    /* dropped item(s) is a ZipFile */
			CommandLine = MakeCMDforUnzip(PathOfDroppedItem);
			if (CommandLine == NULL)
				return false;
			}

		ZipErr = StartApp(CommandLine,true, NULL);
	} /* for ( docCount = 1; docCount <= numDocs; docCount++) */			

	AEDisposeDesc( &myDocList );
	PathOfDroppedItem = StrFree(PathOfDroppedItem);
	
	/* Quit MacZip */
	if ((myErr == noErr) &&
		(ZipErr == 0))
			{
			unsigned long  finalticks;
			Delay((unsigned long)50,&finalticks);
			DoQuit();
			}
		
	return myErr;
} /* DoODocAE */


/********************************************************************************/
/*	Print-Documents-Event 														*/
/********************************************************************************/

pascal OSErr DoPrintAE( AppleEvent *myAppleEvent, AppleEvent *myReply, long refCon )
{
myAppleEvent = myAppleEvent;
myReply = myReply;
refCon = refCon;

/* printing is not implemented */
	return errAEEventNotHandled;	
} /* DoPrintAE */


/********************************************************************************/
/*	Quit-Application-Event 														*/
/********************************************************************************/

pascal OSErr DoQuitAE( AppleEvent *myAppleEvent, AppleEvent *myReply, long refCon )
{
OSErr	AEerr;

myAppleEvent = myAppleEvent;
myReply = myReply;
refCon = refCon;
	
if (noErr != (AEerr = MyGotRequiredParams(myAppleEvent)))
	{
		/* an error occurred:  do the necessary error handling */
		return	AEerr;
	}
	
	/* we should cleanup here */
	
ApplescriptQuitWasCalled = true;

return noErr;
} /* DoQuitAE */


/********************************************************************************/
/*	check the  Parameters 														*/
/********************************************************************************/

OSErr MyGotRequiredParams( AppleEvent *myAppleEvent )
{
	DescType	ignoreType;
	long		actualSize;
	OSErr		myErr;
		
/* Check Attribut keyMissedKeywordAttr in Apple-Event */
	myErr = AEGetAttributePtr( myAppleEvent, keyMissedKeywordAttr, typeWildCard, 
		&ignoreType, nil, 0, &actualSize );

	if ( myErr == errAEDescNotFound )
		return noErr;
	else if (!myErr)			/* you missed a required parameter  */
			return errAEEventNotHandled;
	else					/* the call to AEGetAttributePtr failed   */
			return myErr;
} /* MyGotRequiredParams */




pascal OSErr  MyHandleCMDLine (AppleEvent *theAppleEvent, AppleEvent* reply, long
														handlerRefCon)
{
	OSErr		err = 0;
	DescType	returnedType;
	Size		actualSize;
	char	   *CMDString;

    reply = reply; handlerRefCon = handlerRefCon; 
    
    CMDString = StrCalloc(CMDLineSize);
     
	if ((err = AEGetParamPtr(theAppleEvent, keyDirectObject, typeChar, &returnedType,
								CMDString, CMDLineSize, &actualSize)) != noErr)
		return err;

	/* check for missing parameters   */
	if ((err = MyGotRequiredParams(theAppleEvent)) != noErr)
		return err;
		
    if (actualSize <= CMDLineSize)
        CMDString[actualSize] = 0;		/* Terminate the C string    */
    
    g.CurrentApp = kUnknown;
    
    if (stricmp(CMDString,"NoWarningBoxes") == 0)
    	{
    	g.NoWarningBoxes = true;
    	return err;
    	}
    
    err = ChooseActionStartCommand(CMDString);
            
    CMDString = StrFree(CMDString);

return err;
}



/*
**  checks a file and return true if it's a zip-file
**  I use simply the return value of unzip.
**  unzip -z   ->  display zip comment
*/

Boolean isZipFile(FSSpec *fileToOpen)
{
char *CommandLine, *ArchivePath;
OSErr myErr;
int ExitResult;
long dirID;
Boolean isDirectory;
short tmp_CurrentApp = g.CurrentApp;
g.BeSilent = true;

CommandLine = StrCalloc(NAME_MAX);
ArchivePath = StrCalloc(NAME_MAX);		 

g.CurrentApp = kUnzip;   
g.PathAreOK = true;

GetFullPathFromSpec(ArchivePath, fileToOpen , &myErr);
FSpGetDirectoryID(fileToOpen, &dirID, &isDirectory);
if (isDirectory)  /* Directories aren't a zip archive */
    {
    g.CurrentApp = tmp_CurrentApp;
    g.BeSilent = false;
    return false;
    }

strcpy(CommandLine,"-zqq "); /* display zip comment */
strcat(CommandLine, " \"");
strcat(CommandLine, ArchivePath);		
strcat(CommandLine, "\" ");

ExitResult = StartApp(CommandLine, false, NULL);

ArchivePath = StrFree(ArchivePath);
CommandLine = StrFree(CommandLine);		

g.CurrentApp = tmp_CurrentApp;
g.BeSilent = false;


if (ExitResult == 0)
    return true;
else return false;
}



char *MakeCMDforZip(FSSpec *fileToOpen, long numDocs, char *PathOfDroppedItem)
{
static char	*CommandLine, *ExtractPath, *ZipPath;
Boolean isDirectory;
long    dirID;
char    switches[10];

    CommandLine    = StrCalloc(NAME_MAX);
    ExtractPath    = StrCalloc(NAME_MAX);
    ZipPath        = StrCalloc(NAME_MAX);
  
    g.CurrentApp = kZip;   /* dropped item is a file(s) or folder */
    
    Assert_it(ExtractPath,"ExtractPath == NULL","")
	strcpy(ExtractPath,PathOfDroppedItem);
	strcpy(ZipPath,PathOfDroppedItem);
	
	if (stricmp(getenv("TestArchiveAfterwards"),"yes") == 0)
		g.RunTestArchiveAfterwards = true;
	else 
		g.RunTestArchiveAfterwards = false;

/* build a command-line to zip */
/* command-line is like: (-r) "archive:pathfile" "path:to:archive" */

    FSpGetDirectoryID(fileToOpen, &dirID, &isDirectory);
    				    
	if (isDirectory)  { /* zip the complete dir-tree */	    
		strcpy(switches,"-rS");
		printf("\nDefault switches: %s \n\n",switches);
		strcat(ExtractPath,"*");
	} else {            /* zip one item */
		strcpy(switches,"");
	}
	  				    	
	if (numDocs > 1) { /* I do not support zipping more then
	    one Item at the moment */
		DoAlertUser( eTooManyItemsDropped, false );
	    return NULL;
	} else {
	    createArchiveName(ZipPath);
	}  

	Assert_it(CommandLine,"CommandLine == NULL","")
    strcpy(CommandLine, switches);
	strcat(CommandLine, " \"");
	
	strcat(CommandLine, ZipPath);
	strcat(CommandLine, "\" \"");
	strcat(CommandLine, ExtractPath);
	strcat(CommandLine, "\" ");

    ExtractPath = StrFree(ExtractPath);	
    ZipPath     = StrFree(ZipPath);
    
return CommandLine;
}




char *MakeCMDforUnzip(char *archive_path)
{
char 	*CommandLine, *ExtractPath;

    CommandLine    = StrCalloc(NAME_MAX);
    ExtractPath    = StrCalloc(NAME_MAX);

    g.CurrentApp = kUnzip;
    
	/* build a command-line to unzip */
	/* command-line is like: -d "extract:path" "extract:archive" */

	Assert_it(ExtractPath,"ExtractPath == NULL","")
	strcpy(ExtractPath,archive_path);
	
	if (stricmp(getenv("UniqueUnzipFolders"),"no") == 0)
		ExtractPath[strlen(ExtractPath)-1] = 0;
	else 
		FindNewExtractFolder(ExtractPath); 

	Assert_it(CommandLine,"CommandLine == NULL","")
	strcpy(CommandLine, "-d \"");
	strcat(CommandLine, ExtractPath);
	strcat(CommandLine, "\" \"");
	strcat(CommandLine, archive_path);
	strcat(CommandLine, "\" ");
	
	ExtractPath = StrFree(ExtractPath);	
	
return CommandLine;
}


