#import "Puppeteer.h"
#import "WindowInfo.h"

int
waitForWindowCountToChange(id puppet, int currentWindowCount)
/*
 * Wait for the application's window count to change. Timeout after 1 minute.
 * Return the new window count.
 */
{
	int i, newWindowCount;
	
	for (i=0; i<60; i++) {
		if ((newWindowCount = [puppet windowCount]) != currentWindowCount)
			break;
		sleep(1);
	}

	return newWindowCount;
}

preview(id puppet, char *fileName, BOOL landscape)
{
	id speaker = [puppet appSpeaker], layoutPanel, printPanel, keyWindow;
	int msgDelivered, fileOpened, i, windowCount;
	NXRect frame;

	/*
	 * Ask Preview to open the file.
	 */
	msgDelivered = [speaker openFile:fileName ok:&fileOpened]; 
	if (msgDelivered != 0) {
		fprintf(stderr, "Could not send message to Preview, code = %d\n",
			msgDelivered);
		return;
	}
	if (fileOpened == NO) {
		fprintf(stderr, "Preview could not open %s\n", fileName);
		return;
	}
	/*
	 * Make Preview the active application. This is required
	 * because otherwise the Page Layout menu command is not enabled.
	 */
	[puppet postActivate:YES];
			
	/*
	 * Bring up the Page Layout panel by sending Preview a
	 * cmd-P. Save the current window count.
	 */
	windowCount = [puppet windowCount];
	[puppet postKeyCode:'P' window:NX_KEYWINDOW flags:NX_COMMANDMASK];
			
	/*
	 * Make sure Preview has processed that command. We do that by waiting until
	 * one extra window has appeared.
	 */
	windowCount = waitForWindowCountToChange(puppet, windowCount);
			
	/*
	 * Now we read the frame size of Preview's key window and check
	 * that the size corresponds to that of the layout panel. This
	 * is to check in case the Page Layout menu item was disabled
	 * (eg if the file was .ps instead of .eps), in which case we
	 * would be sending the mouse clicks to the wrong window.
	 */ 
	layoutPanel = [puppet keyWindow];
	[layoutPanel getFrame:&frame];
	if (frame.size.width == 306 && frame.size.height == 323) {
		/*
		 * Select either portrait or landscape mode by clicking on the
		 * appropriate button.
		 */
		[puppet postSingleClick:NX_KEYWINDOW flags:0 x:landscape?130.0:60.0 
			y:64.0];
		/*
		 * Now click the OK button.
		 */
		[puppet postSingleClick:NX_KEYWINDOW flags:0 x:260.0 y:20.0];
		windowCount = waitForWindowCountToChange(puppet, windowCount);
	}
	/*
	 * Do a cmd-p followed by return to print the file.
	 */
	[puppet postKeyCode:'p' window:NX_KEYWINDOW flags:NX_COMMANDMASK];
	windowCount = waitForWindowCountToChange(puppet, windowCount);
	[puppet postKeyCode:'\r' window:NX_KEYWINDOW flags:0];

	/*
	 * Wait for Preview to finish with the print panel.
	 */
	windowCount = waitForWindowCountToChange(puppet, windowCount);
	
	/*
	 * And finally, get rid of the current window with a cmd-w.
	 */
	[puppet postKeyCode:'w' window:NX_KEYWINDOW flags:NX_COMMANDMASK];
}

main(argc, argv)
int argc;
char **argv;
{
	int c, errflg = 0;
	BOOL landscape = NO;
	id puppet, speaker;
	DPSContext ctxt;
	extern int optind;
	extern char *optarg;

	while ((c = getopt(argc, argv, "l")) != EOF)
	switch (c) {
	case 'l':
		landscape = YES;
		break;
	case '?':
	default:
		errflg++;
		break;
	}
	if (errflg) {
		fprintf(stderr, "Usage: previewPuppet [-l] file1.eps [file2.eps ...]\n");
		exit(2);
	}
	
	/*
	 * Because the WindowInfo object sends postscript commands, we have to
	 * create a postscript context for it to run in.
	 */
	ctxt = DPSCreateContext(0, 0, NULL, NULL);
	DPSSetContext(ctxt);
	
	/*
	 * Create the Preview puppet, launching Preview if necessary.
	 */
	puppet = [Puppeteer connectToApp:"Preview" launch:YES];
	if (!puppet) {
		fprintf(stderr, "Could not connect to Preview\n");
		exit(1);
	}
	
	/*
	 * Attach the strings. Preview will then be ready to accept events.
	 */	
	[puppet attachStrings];
	
	/*
	 * Now call Preview to print each file in turn.
	 */
	for (; optind < argc; optind++) {
		preview(puppet, argv[optind], landscape);
	}

	/*
	 * Release strings. This is necessary for Preview to continue to respond to
	 * real user events.
	 */
	[puppet releaseStrings];
	
	DPSDestroyContext(ctxt);
}