#include <CoreServices/CoreServices.h>
#include <Quartz/Quartz.h>
#include <getopt.h>
/*
*/

void showHelp();
void showUsage();

int main (int argc, char * const argv[]) {

	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	int ch;
	int returnValue = 11;

	NSString *inputPath = NULL;
	NSString *outputPath = NULL;
	NSString *userPassword = NULL;
	NSString *ownerPassword = NULL;
	NSString *tempString = NULL;
	NSNumber *tempNumber = NULL;
	NSArray *tempArray = NULL;
	bool isPermitPrinting = true;
	bool isPermitCopying = true;
	bool isDebug = false;

     /* options descriptor */
     static struct option longopts[] = {
			{ "sourcePDFFile",		required_argument,	NULL,	'i' },
			{ "convertedPDFFile",   required_argument,	NULL,	'o' },
			{ "author",				required_argument,	NULL,	'a' },
			{ "creator",			required_argument,	NULL,	'k' },
			{ "title",				required_argument,	NULL,	't' },
			{ "userPassword",		required_argument,	NULL,	'u' },
			{ "ownerPassword",		required_argument,	NULL,	'x' },
			{ "permitPrinting",		required_argument,	NULL,	'p' },
			{ "permitCopying",		required_argument,	NULL,	'c' },
			{ "subject",			required_argument,	NULL,	's' },
			{ "keywords",			required_argument,	NULL,	'w' },
			{ "encryptionKeyLength",		required_argument,	NULL,	'e' },
			{ "debug",				no_argument,		NULL,	'd' },
			{ "help",				no_argument,		NULL,	'h' },
			{ NULL,					0,					NULL,	0 }
     };

	NSString *optValue;
	
	NSMutableDictionary *options = [ NSMutableDictionary dictionaryWithCapacity:10 ];

	while ((ch = getopt_long(argc, argv, "i:o:a:k:t:u:x:p:c:s:w:e:dh", longopts, NULL)) != -1)
		switch (ch) {
			case 'i':
				inputPath = [[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding] stringByExpandingTildeInPath];
				break;
			case 'o':
				outputPath = [[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding] stringByExpandingTildeInPath];
				break;
			case 'a':
				[ options setValue:	[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding]
							forKey:		(void *)kCGPDFContextAuthor ];
				break;
			case 'k':
				[ options setValue:	[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding]
						forKey:	(void *)kCGPDFContextCreator ];
				break;
			case 't':
				[ options setValue:	[NSString stringWithCString: optarg encoding: NSUTF8StringEncoding]
						forKey:	(void *)kCGPDFContextTitle ];
				break;
			case 'u':
				userPassword = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				[ options setValue:userPassword forKey:(void *)kCGPDFContextUserPassword ];
				break;
			case 'x':
				ownerPassword = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				[ options setValue:ownerPassword forKey:(void *)kCGPDFContextOwnerPassword ];
				break;
			case 'p':
				optValue = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				if ( ( [optValue caseInsensitiveCompare:@"YES"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"TRUE"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"1"] == NSOrderedSame ) )	{
					isPermitPrinting = true;
					[ options setValue:	[NSNumber numberWithBool: isPermitPrinting] 
						forKey:	(void *)kCGPDFContextAllowsPrinting ];
				}
				else if ( ( [optValue caseInsensitiveCompare:@"NO"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"FALSE"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"0"] == NSOrderedSame ) )	{
					isPermitPrinting = false;
					[ options setValue:	[NSNumber numberWithBool: isPermitPrinting]
						forKey:	(void *)kCGPDFContextAllowsPrinting ];
				}
				break;
             case 'c':
				optValue = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				if ( ( [optValue caseInsensitiveCompare:@"YES"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"TRUE"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"1"] == NSOrderedSame ) )	{
					isPermitCopying = false;
					[ options setValue:	[NSNumber numberWithBool: isPermitCopying]
						forKey:	(void *)kCGPDFContextAllowsCopying ];
				}
				if ( ( [optValue caseInsensitiveCompare:@"NO"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"FALSE"] == NSOrderedSame )
					|| ( [optValue caseInsensitiveCompare:@"0"] == NSOrderedSame ) )	{
					isPermitCopying = false;
					[ options setValue:	[NSNumber numberWithBool: isPermitCopying] 
						forKey:	(void *)kCGPDFContextAllowsCopying ];
				}
				break;
			case 's':
				tempString = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				[ options setValue:tempString forKey:(void *)kCGPDFContextSubject ];
				break;
			case 'w':
				tempString = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				tempArray = [tempString componentsSeparatedByString:@","];
				[ options setValue:tempArray forKey:(void *)kCGPDFContextKeywords ];
				break;
			case 'e':
				tempString = [NSString stringWithCString: optarg encoding: NSUTF8StringEncoding];
				tempNumber = [NSNumber numberWithInt:[tempString intValue]];
				[ options setValue:tempNumber forKey:(void *)kCGPDFContextEncryptionKeyLength ];
				break;
             case 'h':
				showHelp();
				returnValue = 4;
				goto Exit;
				break;
             case 'd':
				isDebug = YES;
				break;
             default:
				showUsage();
				returnValue = 5;
				goto Exit;
				break;
     }

	if ( ( inputPath == NULL ) || ( outputPath == NULL ) )	{
		printf("You have to specify the source PDF file and converted file.\n");
		showUsage();
		returnValue = 1;
		goto Exit;
	}

	if ( ( [ ownerPassword length] == 0 ) && ( [ userPassword length] != 0 ) )
		[ options setValue:@"" forKey:	(void *)kCGPDFContextOwnerPassword ];

	if ( isDebug )	CFShow(options);

	PDFDocument *pdfDoc = [[PDFDocument alloc] initWithURL: [NSURL fileURLWithPath: inputPath ] ];
	if ( pdfDoc == NULL )	{
		returnValue = 2;
		printf("Input File is not valid.");
		goto Exit;
	}
	if ( ! [pdfDoc writeToFile: outputPath withOptions: options] )	{
		returnValue = 3;
		printf("Error in writing PDF file.");
		goto Exit;
	}
	
	returnValue = 0;
Exit:
	[pool release];

    return returnValue;
}

void showUsage()	{
	printf( "Please check the help message by 'pdfauxinfo --help'.\n\n" );
}

void showHelp()	{
	printf("Description:\n");
	printf("  pdfauxinfo can set the auxiliary information to PDF file using PDFKit in Cocoa.\n");
	printf("  This is the version 2.x command line tool for Leopard only.\n\n");
	printf("Parameters:\n");
	printf("  --sourcePDFFile, -i Input_File_Path            Original PDF File path.\n");
	printf("  --convertedPDFFile, -o Output_File_Path        Converted PDF File path.\n");
	printf("  --author, -a Author_Name                       Author info of the converted PDF.\n");
	printf("  --creator, -k Creator_Name                     Creator info of the converted PDF.\n");
	printf("  --title, -t Title_of_Document                  Title of the converted PDF.\n");
	printf("  --userPassword, -u User_Password               User Password for the converted PDF.\n");
	printf("  --ownerPassword, -x Owner_Password             Owner Password for the converted PDF.\n");
	printf("  --permitPrinting, -p [YES|true|1|NO|false|0]   Permission for printing the converted PDF.\n");
	printf("  --permitCopying, -c  [YES|true|1|NO|false|0]   Permission for copying the text.\n");
	printf("  --subject, -s Subject                          Subject for the converted PDF.\n");
	printf("  --keyword, -k Keyword,Keyword...               Keywords for the converted PDF, devide by ','.\n");
	printf("  --encryptionKeyLength, -e length               Encryption key length by bit.\n");
	printf("  --debug, -d                                    Debug mode.\n");
	printf("  --help, -h                                     Show this message.\n\n");
	printf("For the option permitPrinting and permitCopying, YES or true or 1 means permitting, \n");
	printf("the others means not permitting.\n\n");
	printf("The encryptionKeyLength option must be a multiple of 8 between 40 and 128.\n");
	printf("If this option is not specified, 40 bit will use to encrypt.\n");
	printf("If this option is set to other than 40, 128 bit RC4 will use to encrypt.\n\n");
	printf("Required options are sourcePDFFile and convertedPDFFile.\n\n");
	printf("pdfauxinfo v2.x works just only Mac OS X Leopard or later.\n\n");
}