// TiltViewer.jsx
// Copyright 2007-2009
// Written by Jeffrey Tranberry
// Photoshop for Geeks Version 3.0

/////////////////////////////////////////////////////////////////
// TiltViewer 1.3.1
// http://www.airtightinteractive.com/projects/tiltviewer/
/////////////////////////////////////////////////////////////////

// enable double clicking from the 
// Macintosh Finder or the Windows Explorer
#target photoshop

// Make Photoshop the frontmost application
// in case we double clicked the file
app.bringToFront();


///////////////////////////
//       SET-UP          //
///////////////////////////

var gVersion = 1.3;

// a global variable for the title of the dialog
// this string will also be used for the preferences file I write to disk
// Photoshop Install Directory/Presets/Image Processor/Image Processor.xml for example

var gScriptName = "TiltViewer";

// remember the dialog modes
var saveDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;

try {

	// make sure they are running Photoshop CS2
	CheckVersion();

}

// Lot's of things can go wrong, Give a generic alert and see if they want the details
catch(e) {
	if ( confirm("Sorry, something major happened and I can't continue! Would you like to see more info?" ) ) {
		alert(e);
	}
}

// Save the current preferences
	var startRulerUnits = app.preferences.rulerUnits;
	var startTypeUnits = app.preferences.typeUnits;
	var startDisplayDialogs = app.displayDialogs;

// Set Photoshop to use pixels and display no dialogs
	app.preferences.rulerUnits = Units.PIXELS;
	app.preferences.typeUnits = TypeUnits.PIXELS;
	app.displayDialogs = DialogModes.NO;
	
// Set the script location

	var scriptLocation = findScript() + "0";

// A list of file extensions to skip, keep them lower case

	gFilesToSkip = Array( "db", "xmp", "thm", "txt", "doc", "md0", "tb0", "adobebridgedb", "adobebridgedbt", "bc", "bct", "js", "html", "mov", "xml", "swf" );

// Stuff I don't know much about

	var strButtonBrowse = localize("$$$/JavaScripts/ExportLayersToFiles/Browse=Browse...");
	var strAlertSpecifyDestination = localize("$$$/JavaScripts/ExportLayersToFiles/SpecifyDestination=Please specify an output folder.");
	var strAlertDestinationNotExist = localize("$$$/JavaScripts/ExportLayersToFiles/DestionationDoesNotExist=Output folder does not exist.");
	var strAlertSpecifyInputFolder = localize("$$$/JavaScripts/ExportLayersToFiles/SpecifyInputFolder=Please specify an input folder.");
	var strAlertInputFolderNotExist = localize("$$$/JavaScripts/ExportLayersToFiles/InputFolderDoesNotExist=Input folder does not exist.");

	var exportInfo = new Object();
    
	initExportInfo(exportInfo);  
	
// define the dialog	
// [left, top, right, bottom]
function createDialog(){

	// Create an empty dialog window near the upper left of the screen
	var dlg = new Window('dialog', 'TiltViewer');
	dlg.frameLocation = [100, 100];
	// Add a panel to hold title and 'message text' strings
	dlg.msgPn2 = dlg.add('panel', undefined, 'Input Folder');
	dlg.msgPn2.orientation = "column";
	dlg.msgPn2.alignChildren = 'Right';
	
	dlg.msgPn2.InputFolder = dlg.msgPn2.add('group');
	dlg.msgPn2.InputFolder.orientation = "row";
	dlg.msgPn2.etInputFolder = dlg.msgPn2.add("edittext", undefined, exportInfo.destination.toString());
	dlg.msgPn2.etInputFolder.preferredSize.width = 275;
	dlg.msgPn2.etInputFolder.helpTip = "Choose a folder of images to process.";

	dlg.msgPn2.btnBrowse = dlg.msgPn2.add("button", undefined, strButtonBrowse);
	dlg.msgPn2.btnBrowse.helpTip = "Choose a folder of images to process.";
	dlg.msgPn2.btnBrowse.onClick = function() {
		var defaultFolder = dlg.msgPn2.etInputFolder.text;
		var testFolder = new Folder(dlg.msgPn2.etInputFolder.text);
		if (!testFolder.exists) {
			defaultFolder = "~";
		}
		// var selFolder = Folder.selectDialog(dlg.msgPn2.etInputFolder.text, defaultFolder);
		dlg.selInputFolder = Folder.selectDialog(dlg.msgPn2.etInputFolder.text, defaultFolder);
		if ( dlg.selInputFolder != null ) {
	        dlg.msgPn2.etInputFolder.text = dlg.selInputFolder.fsName;
	    }
		//dlg.msgPn2.defaultElement.active = true;
	}
	// Add a panel to hold title and 'message text' strings
	dlg.msgPn3 = dlg.add('panel', undefined, 'Output Folder');
	dlg.msgPn3.orientation = "column";
	dlg.msgPn3.alignChildren = 'Right';
	
	dlg.msgPn3.Destination = dlg.msgPn3.add('group');
	dlg.msgPn3.Destination.orientation = "row";
	dlg.msgPn3.etDestination = dlg.msgPn3.add("edittext", undefined, exportInfo.destination.toString());
	dlg.msgPn3.etDestination.preferredSize.width = 275;
	dlg.msgPn3.etDestination.helpTip = "Choose a folder to export your webgallery to.";

	dlg.msgPn3.btnBrowse = dlg.msgPn3.add("button", undefined, strButtonBrowse);
	dlg.msgPn3.btnBrowse.helpTip = "Choose a folder to export your webgallery to.";
	dlg.msgPn3.btnBrowse.onClick = function() {
		var defaultFolder = dlg.msgPn3.etDestination.text;
		var testFolder = new Folder(dlg.msgPn3.etDestination.text);
		if (!testFolder.exists) {
			defaultFolder = "~";
		}
		dlg.selOutputFolder = Folder.selectDialog(dlg.msgPn3.etDestination.text, defaultFolder);
		if ( dlg.selOutputFolder != null ) {
	        dlg.msgPn3.etDestination.text = dlg.selOutputFolder.fsName;
	    }
		//dlg.msgPn3.defaultElement.active = true;
	}
	
	
	dlg.msgPnl = dlg.add('panel', undefined, 'SWF Options');
	dlg.msgPnl.orientation = "column";
	dlg.msgPnl.alignChildren = 'right';
	
	dlg.msgPnl.ImageSz = dlg.msgPnl.add('group');
	dlg.msgPnl.ImageSz.orientation = "row";
	dlg.msgPnl.ImageSz.st = dlg.msgPnl.ImageSz.add('statictext', undefined, 'Image Size:');
	dlg.msgPnl.ImageSz.et = dlg.msgPnl.ImageSz.add('edittext', undefined, '640');
	dlg.msgPnl.ImageSz.st = dlg.msgPnl.ImageSz.add('statictext', undefined, 'px');
	dlg.msgPnl.ImageSz.et.preferredSize = [60,20];
	dlg.msgPnl.ImageSz.helpTip = "Resizes the images to the desired dimensions for the webgallery";
	
	dlg.msgPnl.bgColor = dlg.msgPnl.add('group');
	dlg.msgPnl.bgColor.orientation = "row";
	dlg.msgPnl.bgColor.st = dlg.msgPnl.bgColor.add('statictext', undefined, 'Background Color #:');
	dlg.msgPnl.bgColor.et = dlg.msgPnl.bgColor.add('edittext', undefined, '000000');
	dlg.msgPnl.bgColor.st = dlg.msgPnl.bgColor.add('statictext', undefined, '    ');
	dlg.msgPnl.bgColor.et.preferredSize = [60,20];
	dlg.msgPnl.bgColor.helpTip = "Choose a Hex value for the background color";
	
	dlg.msgPnl.frameColor = dlg.msgPnl.add('group');
	dlg.msgPnl.frameColor.orientation = "row";
	dlg.msgPnl.frameColor.st = dlg.msgPnl.frameColor.add('statictext', undefined, 'Frame Color #:');
	dlg.msgPnl.frameColor.et = dlg.msgPnl.frameColor.add('edittext', undefined, 'FFFFFF');
	dlg.msgPnl.frameColor.st = dlg.msgPnl.frameColor.add('statictext', undefined, '    ');
	dlg.msgPnl.frameColor.et.preferredSize = [60,20];
	dlg.msgPnl.frameColor.helpTip = "Choose a Hex value for the frame color";
	
	dlg.msgPnl.backColor = dlg.msgPnl.add('group');
	dlg.msgPnl.backColor.orientation = "row";
	dlg.msgPnl.backColor.st = dlg.msgPnl.backColor.add('statictext', undefined, 'Flipside Background Color #:');
	dlg.msgPnl.backColor.et = dlg.msgPnl.backColor.add('edittext', undefined, 'FFFF00');
	dlg.msgPnl.backColor.st = dlg.msgPnl.backColor.add('statictext', undefined, '    ');
	dlg.msgPnl.backColor.et.preferredSize = [60,20];
	dlg.msgPnl.backColor.helpTip = "Choose a Hex value for the flipside background color";
	
	dlg.msgPnl.bkgndInnerColor = dlg.msgPnl.add('group');
	dlg.msgPnl.bkgndInnerColor.orientation = "row";
	dlg.msgPnl.bkgndInnerColor.st = dlg.msgPnl.bkgndInnerColor.add('statictext', undefined, 'Gradient Center Color #:');
	dlg.msgPnl.bkgndInnerColor.et = dlg.msgPnl.bkgndInnerColor.add('edittext', undefined, '333333');
	dlg.msgPnl.bkgndInnerColor.st = dlg.msgPnl.bkgndInnerColor.add('statictext', undefined, '    ');
	dlg.msgPnl.bkgndInnerColor.et.preferredSize = [60,20];
	dlg.msgPnl.bkgndInnerColor.helpTip = "Choose a Hex value for the gradient center color";
	
	dlg.msgPnl.bkgndOuterColor = dlg.msgPnl.add('group');
	dlg.msgPnl.bkgndOuterColor.orientation = "row";
	dlg.msgPnl.bkgndOuterColor.st = dlg.msgPnl.bkgndOuterColor.add('statictext', undefined, 'Gradient Edge Color #:');
	dlg.msgPnl.bkgndOuterColor.et = dlg.msgPnl.bkgndOuterColor.add('edittext', undefined, '000000');
	dlg.msgPnl.bkgndOuterColor.st = dlg.msgPnl.bkgndOuterColor.add('statictext', undefined, '    ');
	dlg.msgPnl.bkgndOuterColor.et.preferredSize = [60,20];
	dlg.msgPnl.bkgndOuterColor.helpTip = "Choose a Hex value for the gradient edge color";
	
	dlg.msgPnl.bkgndColor = dlg.msgPnl.add('group');
	dlg.msgPnl.bkgndColor.orientation = "row";
	dlg.msgPnl.bkgndColor.st = dlg.msgPnl.bkgndColor.add('statictext', undefined, 'Gradient Center Color #:');
	dlg.msgPnl.bkgndColor.et = dlg.msgPnl.bkgndColor.add('edittext', undefined, 'FFFF00');
	dlg.msgPnl.bkgndColor.st = dlg.msgPnl.bkgndColor.add('statictext', undefined, '    ');
	dlg.msgPnl.bkgndColor.et.preferredSize = [60,20];
	dlg.msgPnl.bkgndColor.helpTip = "Choose a Hex value for the gradient center color";
	
	dlg.msgPnl.Columns = dlg.msgPnl.add('group');
	dlg.msgPnl.Columns.orientation = "row";
	dlg.msgPnl.Columns.st = dlg.msgPnl.Columns.add('statictext', undefined, 'Number of Image Columns:');
	dlg.msgPnl.Columns.et = dlg.msgPnl.Columns.add('edittext', undefined, '5');
	dlg.msgPnl.Columns.Valuest = dlg.msgPnl.Columns.add('statictext', undefined, '    ');
	dlg.msgPnl.Columns.et.preferredSize = [60,20];
	dlg.msgPnl.Columns.helpTip = "The number of columns of images in the webgallery.";
	
	dlg.msgPnl.Rows = dlg.msgPnl.add('group');
	dlg.msgPnl.Rows.orientation = "row";
	dlg.msgPnl.Rows.st = dlg.msgPnl.Rows.add('statictext', undefined, 'Number of Image Rows:');
	dlg.msgPnl.Rows.et = dlg.msgPnl.Rows.add('edittext', undefined, '5');
	dlg.msgPnl.Rows.Valuest = dlg.msgPnl.Rows.add('statictext', undefined, '    ');
	dlg.msgPnl.Rows.et.preferredSize = [60,20];
	dlg.msgPnl.Rows.helpTip = "The number of rows of images in the webgallery.";	
	
	// Add a panel with buttons to test parameters and
	dlg.buttonPanel = dlg.add('panel', undefined);
	dlg.buttonPanel.orientation = "row";
	//dlg.buttonPanel.cancelBtn = dlg.buttonPanel.add('button', undefined, '  Cancel   ', {name:'cancel'});
	//dlg.buttonPanel.testBtn = dlg.buttonPanel.add('button', undefined, '   Build Photo Gallery   ');
	dlg.buttonPanel.cancelBtn = dlg.buttonPanel.add ('button', undefined,'Cancel');
	dlg.buttonPanel.runBtn = dlg.buttonPanel.add ('button', undefined,'Build Web Gallery');

	return dlg;
	}

	var params = new Array();
	params['InputFolder'] = "";
	params['OutputFolder'] = "";
	params['ImageSize'] = "";
	params['BackgroundColor'] = "";
	params['frameColor'] = "";
	params['backColor'] = "";
	params['bkgndInnerColor'] = "";
	params['bkgndOuterColor'] = "";
	params['NumberofColumns'] = "";
	params['NumberofRows'] = "";

	
	LoadParamsFromDisk( GetDefaultParamsFile(), params );

	function initializeDialog (PostcardViewer){
	with(PostcardViewer) {
		
	msgPn2.etInputFolder.value = params['InputFolder'];
	msgPn3.etDestination.value = params['OutputFolder'];
	msgPnl.ImageSz.et.value = params['ImageSize'];
	msgPnl.bgColor.et.value = params['BackgroundColor'];
	msgPnl.frameColor.et.value = params['FrameColor'];
	msgPnl.backColor.et.value = params['FlipsideBackgroundColor'];
	msgPnl.bkgndInnerColor.et.value = params['GradientCenterColor'];
	msgPnl.bkgndOuterColor.et.value = params['GradientEdgeColor'];
	msgPnl.Columns.et.value = params['NumberofColumns'];
	msgPnl.Rows.et.value = params['NumberofRows'];
	
	// Run the web photo gallery
	// checking for valid settings
	buttonPanel.runBtn.onClick = function() {
	
	// check if the input folder setting is proper
			var inptfld = PostcardViewer.msgPn2.etInputFolder.text;
			if (inptfld.length == 0) {
				alert(strAlertSpecifyInputFolder);
				return;
			}
			var testFolder = new Folder(inptfld);
			if (!testFolder.exists) {
				alert(strAlertInputFolderNotExist);
				return;
			}
			
			// check if the output folder setting is proper
			var destination = PostcardViewer.msgPn3.etDestination.text;
			if (destination.length == 0) {
				alert(strAlertSpecifyDestination);
				return;
			}
			var testFolder = new Folder(destination);
			if (!testFolder.exists) {
				alert(strAlertDestinationNotExist);
				return;
			}
			
			// See if the input folder and the output folder are the same
			if (PostcardViewer.msgPn3.etDestination.text == PostcardViewer.msgPn2.etInputFolder.text) {
				var result = confirm("Are you sure you want your output folder to be the same as your input folder");
				if (result) {
				} else {
					return;
				}
    		}
			
			// check to see if the image size is setting is proper
			var imageSizeStr = isNaN(PostcardViewer.msgPnl.ImageSz.et.text);
			if (imageSizeStr == true) {
        		alert("Please enter a valid number 300-1600 for 'Image Size'");
        		return;
        	}
    		if (!(PostcardViewer.msgPnl.ImageSz.et.text >= 300 && PostcardViewer.msgPnl.ImageSz.et.text <= 1600)) {
				alert("You must enter a number between 300-1600 for 'Image Size'");
				return;
    		}
    		
    		// check to see if the Number of Image Columns setting is proper
			var columnsStr = isNaN(PostcardViewer.msgPnl.Columns.et.text);
			if (columnsStr == true) {
        		alert("Please enter a valid number 3-12 for 'Number of Image Columns'");
        		return;
        	}
    		if (!(PostcardViewer.msgPnl.Columns.et.text >= 3 && PostcardViewer.msgPnl.Columns.et.text <= 12)) {
				alert("You must enter a number between 3-12 for 'Number of Image Columns'");
				return;
    		}
		
			// check to see if the Number of Image Rows setting is proper
			var rowsStr = isNaN(PostcardViewer.msgPnl.Rows.et.text);
			if (rowsStr == true) {
        		alert("Please enter a valid number 3-12 for 'Number of Image Rows'");
        		return;
        	}
    		if (!(PostcardViewer.msgPnl.Rows.et.text >= 3 && PostcardViewer.msgPnl.Rows.et.text <= 12)) {
				alert("You must enter a number between 3-12 for 'Number of Image Rows'");
				return;
    		}
    		
    		
    		
	close( 1 );
	}
	buttonPanel.cancelBtn.onClick = function() { close( 2 ); }
	}
	}

	function runDialog(PostcardViewer){

	// Warn the user if they have an open document and exit the script with return
	if (documents.length > 0){
		alert ("This script requires that there are no open documents to run.");
	return;
	}		
		
	return PostcardViewer.show()
	}
		
	var PostcardViewer = createDialog()	
	initializeDialog(PostcardViewer)
	
	
	
	
//=====================Start=====================================================

	if (runDialog(PostcardViewer) == 1){
	// transfer values from the dialog to my internal params
	params['InputFolder'] = PostcardViewer.msgPn2.etInputFolder.value;
	params['OutputFolder'] = PostcardViewer.msgPn3.etDestination.value;
	params['ImageSize'] = PostcardViewer.msgPnl.ImageSz.et.value;
	params['BackgroundColor'] = PostcardViewer.msgPnl.bgColor.et.value;
	params['FrameColor'] = PostcardViewer.msgPnl.frameColor.et.value;
	params['FlipsideBackgroundColor'] = PostcardViewer.msgPnl.backColor.et.value;
	params['GradientCenterColor'] = PostcardViewer.msgPnl.bkgndInnerColor.et.value;
	params['GradientEdgeColor'] = PostcardViewer.msgPnl.bkgndOuterColor.et.value;
	params['NumberofColumns'] = PostcardViewer.msgPnl.Columns.et.value;
	params['NumberofRows'] = PostcardViewer.msgPnl.Rows.et.value;
	
	// Save the params from the above
	SaveParamsToDisk( GetDefaultParamsFile(), params );
	
	// Gets the output folder from the UI
			var inputFolder = PostcardViewer.msgPn2.etInputFolder.text;
			//alert(inputFolder);
			
			// Gets the output folder from the UI
			var outputFolder = PostcardViewer.msgPn3.etDestination.text;
			//alert(outputFolder);
			
			// Gets the Image Size from the UI
			var imageSize = PostcardViewer.msgPnl.ImageSz.et.text;
			//alert(imageSize);
			
			// Determine line feed and then save out text files.  Note that "Desktop" is localized
			// on Win, when so we don't reference the desktop if it can not be found.
			
				if (File.fs == "Windows") {
					fileLineFeed = "windows";
					var desktopFolder = Folder("~/" + outputFolder);
					if (desktopFolder.exists != 1) {
						var ImageFileFolder = new Folder(outputFolder + "/images");
					} else {
						var ImageFileFolder = new Folder("~/" + outputFolder + "/images");
					}
				} else {
					fileLineFeed = "macintosh";
					var ImageFileFolder = new Folder(outputFolder + "/images");
				}
				ImageFileFolder.create();
				
			// Generate HTML File    
    
			var HTMLFilePath = outputFolder + "/" + "index.html";
			var HTMLFile = File(HTMLFilePath);
			HTMLFile.remove();
			var HTMLFilePath = new File(outputFolder + "/" + "index.html");
    
			// Generate XML File 
    
    		var XMLFilePath = outputFolder + "/" + "gallery.xml";
			var XMLFile = File(XMLFilePath);
			XMLFile.remove();
			var XMLFilePath = new File(outputFolder + "/" + "gallery.xml");
    
			// Copy SWF File from the Presets/Scripts folder to the specified output folder 
  
			var SWFFilePath = scriptLocation.slice(0,-15) + "TiltViewer.swf";
			var SWFFile = File(SWFFilePath);
			SWFFile.copy(outputFolder + "/TiltViewer.swf");
    
			// Copy .js File from the Presets/Scripts folder to the specified output folder 
  
			var JSFilePath = scriptLocation.slice(0,-15) + "~swfobject.js";
			var JSFile = File(JSFilePath);
			JSFile.copy(outputFolder + "/swfobject.js");
			
			// Copy ReadMe File from the Presets/Scripts folder to the specified output folder 
  
			var ReadMeFilePath = scriptLocation.slice(0,-15) + "readme.html";
			var ReadMeFile = File(ReadMeFilePath);
			ReadMeFile.copy(outputFolder + "/readme.html");

			// Write out XML Header to the file created in the set-up

			writeXMLHeader(XMLFile);
			
			// Open and process a folder of Images
			
			OpenFolder(PostcardViewer.selInputFolder, PostcardViewer.selOutputFolder, XMLFile, imageSize);
			
			// Write out XML Footer to the file created in the set-up
	
			writeXMLFooter(XMLFile);
			
			// Write out all the HTML to the file created in the set-up
	
			writeHTMLDoc(HTMLFile, PostcardViewer.msgPnl.bgColor.et.text);
			
			// launch the web gallery in a browser
			
			File(outputFolder + "/index.html").execute();

	// Return the app preferences
	app.preferences.rulerUnits = startRulerUnits;
	app.preferences.typeUnits = startTypeUnits;
	app.displayDialogs = saveDialogMode;
	
	
	

} // the end






///////////////////////
// Helper Functions //
///////////////////////


///////////////////////////////////////////////////////////////////////////////
// Function: initExportInfo
// Usage: create our default parameters
// Input: a new Object
// Return: a new object with params set to default
///////////////////////////////////////////////////////////////////////////////
function initExportInfo(exportInfo) {
    exportInfo.destination = new String("");
    exportInfo.fileNamePrefix = new String("untitled_");
    exportInfo.visibleOnly = false;
//    exportInfo.fileType = psdIndex;
    exportInfo.icc = true;
    exportInfo.jpegQuality = 8;
    exportInfo.psdMaxComp = true;
    exportInfo.tiffCompression = TIFFEncoding.NONE;
    exportInfo.tiffJpegQuality = 8;
    exportInfo.pdfEncoding = PDFEncoding.JPEG;
    exportInfo.pdfJpegQuality = 8;
    exportInfo.targaDepth = TargaBitsPerPixels.TWENTYFOUR;
    exportInfo.bmpDepth = BMPDepthType.TWENTYFOUR;

    try {
        exportInfo.destination = Folder(app.activeDocument.fullName.parent).fsName; // destination folder
        var tmp = app.activeDocument.fullName.name;
        exportInfo.fileNamePrefix = decodeURI(tmp.substring(0, tmp.indexOf("."))); // filename body part
    } catch(someError) {
        exportInfo.destination = new String("");
//        exportInfo.fileNamePrefix = app.activeDocument.name; // filename body part
    }
}
    
// Find the location where this script resides

function findScript() {
	var where = "";
	try {
		FORCEERROR = FORCERRROR;
	}
	catch(err) {
		// alert(err.fileName);
		// alert(File(err.fileName).exists);
		where = File(err.fileName);
	}
	return where;
}

////////////////////////////
// File Writing Functions //
////////////////////////////

// Write out image name XML
/*
    function writeXMLDocRef() {
        writeXML("<IMAGE><NAME>" + app.activeDocument.name + "</NAME></IMAGE>" + "\n");
    }
*/
    function writeXMLDocRef() {
        writeXML(
'		<photo imageurl="images/' + app.activeDocument.name + '" showFlipButton="true">' + "\n" +
'			<title>' + app.activeDocument.name + '</title>' + "\n" +
'			<description></description>' + "\n" +
'		</photo>' + "\n");
    }

// Write out XML header

    function writeXMLHeader(fileType) {
    	XMLFile = fileType;
		writeXML("<tiltviewergallery>" + "\n" +
"	<photos>" + "\n");
    }
    
// Write out XML footer

    function writeXMLFooter(fileType) {
    	XMLFile = fileType;
		writeXML(
"	</photos>" + "\n" +
"</tiltviewergallery>");
    }

// Write XML file

    function writeXML(log) {
        try {
            if(XMLFile.exists) {
                XMLFile.open ("e");
                XMLFile.seek (0,2);      // Move to EOF
            } else {
            XMLFile.open ("w");          // Add unicode marker if we change to XML file format for this log file
        }
        XMLFile.encoding = "UTF8"; // set UTF8
        XMLFile.write(log);
        XMLFile.close();
        } catch (e) {
            alert(e);
        } finally {
        }
        return;
    }
    
// Write index HTML file

    function writeHTML(log) {
        try {
            if(HTMLFile.exists) {
                HTMLFile.open ("e");
                HTMLFile.seek (0,2);      // Move to EOF
            } else {
            HTMLFile.open ("w");          // Add unicode marker if we change to XML file format for this log file
        }
        HTMLFile.encoding = "UTF8"; // set UTF8
        HTMLFile.write(log);
        HTMLFile.close();
        } catch (e) {
            alert(e);
        } finally {
        }
        return;
    }
    

// Function for returning current date and time

    function getDateTime() {
        var date = new Date();
        var dateTime = "";
        if ((date.getMonth() + 1) < 10) {
            dateTime += "0" + (date.getMonth() + 1) + "/";
        } else {
            dateTime += (date.getMonth() + 1) + "/";
        }
        if (date.getDate() < 10) {
            dateTime += "0" + date.getDate() + "/";
        } else {
            dateTime += date.getDate() + "/";
        }
        dateTime += date.getFullYear() + ", ";
        if (date.getHours() < 10) {
            dateTime += "0" + date.getHours() + ":";
        } else {
            dateTime += date.getHours() + ":";
        }
        if (date.getMinutes() < 10) {
            dateTime += "0" + date.getMinutes() + ":";
        } else {
            dateTime += date.getMinutes() + ":";
        }
        if (date.getSeconds() < 10) {
            dateTime += "0" + date.getSeconds();
        } else {
            dateTime += date.getSeconds();
        }
        return dateTime;
    }
    
// resetPrefs function for resetting the preferences

	function resetPrefs() {
		preferences.rulerUnits = startRulerUnits;
		preferences.typeUnits = startTypeUnits;
		displayDialogs = startDisplayDialogs;
	}
    
////////////////////////////////////
// File Opening/Closing Functions //
////////////////////////////////////
    
// Given the a Folder of files, open them

function OpenFolder(inputFolder, outputFolder, fileType, imageSize) {
        var filesOpened = 0;
        //alert(inputFolder);
        //alert(outputFolder);
        var fileList = inputFolder.getFiles();
        for ( var i = 0; i < fileList.length; i++ ) {
        		   // Make sure all the files in the folder are compatible with PS
                if ( fileList[i] instanceof File && ! fileList[i].hidden && ! IsFileOneOfThese( fileList[i], gFilesToSkip )) {
                        open( fileList[i] );
                        filesOpened++;
                        var docRef = activeDocument;

					if (!(docRef.height * 1 < imageSize * 1 || docRef.width * 1 < imageSize * 1)){
						//alert(docRef.height * 1 + imageSize * 1);
						//alert(docRef.width + imageSize);
						if (docRef.height > docRef.width)
							{
							resizePortrait(imageSize);
							}
						else
							{
							resizeLandscape(imageSize);
							}	
					}
						
					resolveColorModes();
						
					app.activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC);
					
					app.activeDocument.flatten();
					
					saveJPG(outputFolder + "/images/");

					writeXMLDocRef(fileType);

                 fileClose(SaveOptions.DONOTSAVECHANGES);

                }
        }
        return filesOpened;
}


// given a file name and a list of extensions
// determine if this file is in the list of extensions

function IsFileOneOfThese( inFileName, inArrayOfFileExtensions ) {
	var lastDot = inFileName.toString().lastIndexOf( "." );
	if ( lastDot == -1 ) {
		return false;
	}
	var strLength = inFileName.toString().length;
	var extension = inFileName.toString().substr( lastDot + 1, strLength - lastDot );
	extension = extension.toLowerCase();
	for (var i = 0; i < inArrayOfFileExtensions.length; i++ ) {
		if ( extension == inArrayOfFileExtensions[i] ) {
			return true;
		}
	}
	return false;
}


// fileClose function for closing current document

function fileClose(options) {
	
		app.activeDocument.close(options);
}

////////////////////////////////
// Image Processing Functions //
////////////////////////////////

// resize landscape

function resizeLandscape(imageSize) {
//alert(imageSize);
var id3 = charIDToTypeID( "ImgS" );
    var desc2 = new ActionDescriptor();
    var id4 = charIDToTypeID( "Wdth" );
    var id5 = charIDToTypeID( "#Pxl" );
    desc2.putUnitDouble( id4, id5, imageSize );
    var id6 = charIDToTypeID( "Rslt" );
    var id7 = charIDToTypeID( "#Rsl" );
    desc2.putUnitDouble( id6, id7, 72.000000 );
    var id8 = stringIDToTypeID( "scaleStyles" );
    desc2.putBoolean( id8, true );
    var id9 = charIDToTypeID( "CnsP" );
    desc2.putBoolean( id9, true );
    var id10 = charIDToTypeID( "Intr" );
    var id11 = charIDToTypeID( "Intp" );
    var id12 = charIDToTypeID( "Bcbc" );
    desc2.putEnumerated( id10, id11, id12 );
executeAction( id3, desc2, DialogModes.NO );
}

// resize Portrait

function resizePortrait(imageSize) {
//alert(imageSize);
var id15 = charIDToTypeID( "ImgS" );
    var desc4 = new ActionDescriptor();
    var id16 = charIDToTypeID( "Hght" );
    var id17 = charIDToTypeID( "#Pxl" );
    desc4.putUnitDouble( id16, id17, imageSize );
    var id18 = charIDToTypeID( "Rslt" );
    var id19 = charIDToTypeID( "#Rsl" );
    desc4.putUnitDouble( id18, id19, 72.000000 );
    var id20 = stringIDToTypeID( "scaleStyles" );
    desc4.putBoolean( id20, true );
    var id21 = charIDToTypeID( "CnsP" );
    desc4.putBoolean( id21, true );
    var id22 = charIDToTypeID( "Intr" );
    var id23 = charIDToTypeID( "Intp" );
    var id24 = charIDToTypeID( "Bcbc" );
    desc4.putEnumerated( id22, id23, id24 );
executeAction( id15, desc4, DialogModes.NO );
}

// Save JPG

function saveJPG(filePath){
var jpegOptions = new JPEGSaveOptions();
jpegOptions.quality = 10;
jpegOptions.embedColorProfile = false;
app.activeDocument.saveAs( File( filePath), jpegOptions, false);
}

function resolveColorModes(){
	// Remove all alpha channels
	app.activeDocument.channels.removeAll();

	if(app.activeDocument.bitsPerChannel == BitsPerChannelType.SIXTEEN || app.activeDocument.bitsPerChannel == BitsPerChannelType.THIRTYTWO) {

		app.activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;
		
		}
	if(app.activeDocument.mode == DocumentMode.BITMAP) { 
	
	app.activeDocument.changeMode(ChangeMode.GRAYSCALE);
	app.activeDocument.changeMode(ChangeMode.RGB); 
	
	} else if (app.activeDocument.mode == DocumentMode.CMYK){ 
	app.activeDocument.changeMode(ChangeMode.RGB); 
	} else if (app.activeDocument.mode == DocumentMode.INDEXEDCOLOR){ 
	app.activeDocument.changeMode(ChangeMode.RGB); 
	}
}

///////////////////////////////
// Document Set-up Functions //
///////////////////////////////

// Write out HTML File

    function writeHTMLDoc(fileType, bgColorStr) {
        HTMLFile = fileType;
        writeHTML(
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">' + '\n' +
'<head>' + '\n' +
'<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />' + '\n' +
'<title>TiltViewer</title>' + '\n' +
'<script type="text/javascript" src="swfobject.js"></script>' + '\n' +
'<style type="text/css">	' + '\n' +
'	/* hide from ie on mac \\*/' + '\n' +
'	html {' + '\n' +
'		height: 100%;' + '\n' +
'		overflow: hidden;' + '\n' +
'	}' + '\n' + '\n' +
	
'	#flashcontent {' + '\n' +
'		height: 100%;' + '\n' +
'	}' + '\n' +
'	/* end hide */' + '\n' + '\n' +

'	body {' + '\n' +
'		height: 100%;' + '\n' +
'		margin: 0;' + '\n' +
'		padding: 0;' + '\n' +
'		background-color: #' + bgColorStr + ';' + '\n' +
'		color:#ffffff;' + '\n' +
'		font-family:sans-serif;' + '\n' +
'		font-size:40;' + '\n' +
'	}' + '\n' + '\n' +
'	a {' + '\n' +
'		color:#cccccc;' + '\n' +
'	}' + '\n' +
'</style>' + '\n' +
'</head>' + '\n' +
'<body>' + '\n' +
'	<div id="flashcontent">TiltViewer requires JavaScript and the latest Flash Player. <a href="http://www.macromedia.com/go/getflashplayer/">Get Flash here.</a> </div>	' + '\n' +
'	<script type="text/javascript">' + '\n' + '\n' +
'		var fo = new SWFObject("TiltViewer.swf", "viewer", "100%", "100%", "9.0.28", "#' + bgColorStr + '");' + '\n' + '\n' +
'		// TILTVIEWER CONFIGURATION OPTIONS' + '\n' +
'		// To use an option, uncomment it by removing the "//" at the start of the line' + '\n' +
'		// For a description of config options, go to: ' + '\n' +
'		// http://www.airtightinteractive.com/projects/tiltviewer/config_options.html' + '\n' + '\n' +
															
'		//FLICKR GALLERY OPTIONS' + '\n' +
'		// To use images from Flickr, uncomment this block' + '\n' +
'		//fo.addVariable("useFlickr", "true");' + '\n' +
'		//fo.addVariable("user_id", "48508968@N00");' + '\n' +
'		//fo.addVariable("tags", "jump,smile");' + '\n' +
'		//fo.addVariable("tag_mode", "all");' + '\n' +
'		//fo.addVariable("showTakenByText", "true");' + '\n' + '\n' +			

'		// XML GALLERY OPTIONS' + '\n' +
'		// To use local images defined in an XML document, use this block' + '\n' +		
'		fo.addVariable("useFlickr", "false");' + '\n' +
'		fo.addVariable("xmlURL", "gallery.xml");' + '\n' +
'		fo.addVariable("maxJPGSize","' + imageSize + '");' + '\n' + '\n' +
		
'		//GENERAL OPTIONS' + '\n' +
'		fo.addVariable("useReloadButton", "false");' + '\n' +
'		fo.addVariable("columns", "' + PostcardViewer.msgPnl.Columns.et.text + '");' + '\n' +
'		fo.addVariable("rows", "' + PostcardViewer.msgPnl.Rows.et.text + '");' + '\n' +
'		//fo.addVariable("showFlipButton", "true");' + '\n' +
'		//fo.addVariable("showLinkButton", "true");' + '\n' +		
'		//fo.addVariable("linkLabel", "View image info");' + '\n' +
'		fo.addVariable("frameColor", "0x' + PostcardViewer.msgPnl.frameColor.et.text + '");' + '\n' +
'		fo.addVariable("backColor", "0x' + PostcardViewer.msgPnl.backColor.et.text + '");' + '\n' +
'		fo.addVariable("bkgndInnerColor", "0x' + PostcardViewer.msgPnl.bkgndInnerColor.et.text + '");' + '\n' +
'		fo.addVariable("bkgndOuterColor", "0x' + PostcardViewer.msgPnl.bkgndOuterColor.et.text + '");' + '\n' +				
'		//fo.addVariable("langGoFull", "Go Fullscreen");' + '\n' +
'		//fo.addVariable("langExitFull", "Exit Fullscreen");' + '\n' +
'		//fo.addVariable("langAbout", "About");' + '\n' + '\n' +			
		
'		// END TILTVIEWER CONFIGURATION OPTIONS' + '\n' + '\n' +
		
'		fo.addParam("allowFullScreen","true");' + '\n' +
'		fo.write("flashcontent");	' + '\n' +
'	</script>	' + '\n' +
'</body>' + '\n' +
'</html>');
    }

// CheckVersion
function CheckVersion() {
	var numberArray = version.split(".");
	if ( numberArray[0] < 9 ) {
		alert( "You must use Photoshop CS2 or later to run this script!" );
		throw( "You must use Photoshop CS2 or later to run this script!" );
	}
}

// load my params from the xml file on disk if it exists
// gParams["myoptionname"] = myoptionvalue
// I wrote a very simple xml parser, I'm sure it needs work
function LoadParamsFromDisk ( loadFile, params ) {
	// var params = new Array();
	if ( loadFile.exists ) {
		loadFile.open( "r" );
		var projectSpace = ReadHeader( loadFile );
		if ( projectSpace == GetScriptNameForXML() ) {
			while ( ! loadFile.eof ) {
				var starter = ReadHeader( loadFile );
				var data = ReadData( loadFile );
				var ender = ReadHeader( loadFile );
				if ( ( "/" + starter ) == ender ) {
					params[starter] = data;
				}
				// force boolean values to boolean types
				if ( data == "true" || data == "false" ) {
					params[starter] = data == "true";
				}
			}
		}
		loadFile.close();
		if ( params["version"] != gVersion ) {
			// do something here to fix version conflicts
			// this should do it
			params["version"] = gVersion;
		}
	} 
	return params;
}

// save out my params, this is much easier
function SaveParamsToDisk ( saveFile, params ) {
	saveFile.encoding = "UTF8";
	saveFile.open( "w", "TEXT", "????" );
	// unicode signature, this is UTF16 but will convert to UTF8 "EF BB BF"
	saveFile.write("\uFEFF"); 
	var scriptNameForXML = GetScriptNameForXML();
	saveFile.writeln( "<" + scriptNameForXML + ">" );
	for ( var p in params ) {
		saveFile.writeln( "\t<" + p + ">" + params[p] + "</" + p + ">" );
	}
	saveFile.writeln( "</" + scriptNameForXML + ">" );
	saveFile.close();
}

// you can't save certain characters in xml, strip them here
// this list is not complete
function GetScriptNameForXML () {
	var scriptNameForXML = new String( gScriptName );
	var charsToStrip = Array( " ", "'", "." );
	for (var a = 0; a < charsToStrip.length; a++ )  {
		var nameArray = scriptNameForXML.split( charsToStrip[a] );
		scriptNameForXML = "";
		for ( var b = 0; b < nameArray.length; b++ ) {
			scriptNameForXML += nameArray[b];
		}
	}
	return scriptNameForXML;
}

// figure out what I call my params file
function GetDefaultParamsFile() {
	var paramsFolder = new Folder( path + "/Presets/" + gScriptName );
	paramsFolder.create();
	return ( new File( paramsFolder + "/" + gScriptName + ".xml" ) );
}

// a very crude xml parser, this reads the "Tag" of the <Tag>Data</Tag>
function ReadHeader( inFile ) {
	var returnValue = "";
	if ( ! inFile.eof ) {
		var c = "";
		while ( c != "<" && ! inFile.eof ) {
			c = inFile.read( 1 );
		}
		while ( c != ">" && ! inFile.eof ) {
			c = inFile.read( 1 );
			if ( c != ">" ) {
				returnValue += c;
			}
		}
	} else {
		returnValue = "end of file";
	}
	return returnValue;
}

// very crude xml parser, this reads the "Data" of the <Tag>Data</Tag>
function ReadData( inFile ) {
	var returnValue = "";
	if ( ! inFile.eof ) {
		var c = "";
		while ( c != "<" && ! inFile.eof ) {
			c = inFile.read( 1 );
			if ( c != "<" ) {
				returnValue += c;
			}
		}
		inFile.seek( -1, 1 );
	}
	return returnValue;
}

