﻿
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
*  Copyright 2011 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any.  The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*
* $DateTime:  $
*
* Adobe Output Module 4.0
*
* MediaGallery Originally Written by Quality Process Incorporated, Enhanced by
* Adobe Systems China. Contact Sheet written by Adobe Systems China.
* 
*
**************************************************************************/

AOM.AMG = {};

// a smattering of configuration items
AOM.AMG.trackDocId = false;
AOM.AMG.disableColorpickerGetErrorMessages = true;
AOM.AMG.placeLogFileInUserHome = false;
AOM.AMG.verbose = false;

// enable the next line to override the default color of the design window background
//AOM.AMG.designWindowBackground =  [0.2706, 0.2706, 0.2706];

AOM.AMG.isValid = true;
AOM.AMG.checkEditTextValidOnMac = function() {
	if (File.fs == "Macintosh") {
		if (AOM.AMG.isValid == false) {
			AOM.AMG.isValid = true;
			return false;
		}
	}
	return true;
}

AOM.AMG.localize = function (s)
{
	// TODO - Add code to set up proper locale translation file.
	// Note - This gets called for lots of strings that do not
	//		  need to be localized. It may be faster to test
	//		  for '$$$/' at the start of the line. Of course,
	//		  it may also be much faster to continue to let the
	//		  native localize figure it out for us...
	return AOM.localize(s);
}
/*
 *  AMG 2.0: To Do:
 *    The following function is an adaption of AMG.eventHandler(). Since in 2.0 AMG
 *    is no longer an application exclusively owns an entire tabbed palette, the
 *    event handler need to be change.  
 */ 
AOM.AMG.switchTo = function(tabbedPalette, container, showCabinet)
{
    var f = new Folder(AOM.AMG.Paths.user);
    if (!f.exists) {
    	if (!f.create())
    		AOM.alert("Could not create workarea (" + f.fsName + ")");
    }

	var document = tabbedPalette.content.document;
	if (document.aomJsFuncs == undefined)
		document.aomJsFuncs = {};
	
	if (!AOM.AMG.userInputCreated(document))
	{
		var error = function (s) {return AOM.AMG.Log.writeError("AOM.AMG.switchTo - " + s);}
		
		var amgUserInput = new AOM.AmgUserInput();
		if (amgUserInput == undefined)
			return error("userInput is undefined");
		document.aomJsFuncs.amgUserInput = amgUserInput;
	}
	if (AOM.AMG.ftpPresetUserInput == undefined) {
		var ftpPresetUserInput = new AOM.AmgFTPPresetUserInput();
		if (ftpPresetUserInput == undefined)
			return AOM.AMG.Log.writeError("AOM.AMG.switchTo - ftpPresetUserInput is undefined");
		
		AOM.AMG.ftpPresetUserInput = function() {
			return ftpPresetUserInput;
		}
	}

	/* 
     * AMG 2.0: Move the following section out of the if-branch.
     *          In 1.0, AMG has its own tabbed palette exclusively so all controls
     *          need to be created only once. In 2.0, AMG share one palette with
     *          Contact Sheet and the switch between the two is performed on user's
     *          demand.                    
	 */
	var amgDesignWindow = new AOM.AmgDesignWindow(tabbedPalette, container, showCabinet);
	if (amgDesignWindow == undefined)
		return error("designWindow is undefined");
	document.aomJsFuncs.designWindow = function () {return amgDesignWindow;}
}

// shortcuts to the document specific functions stored in the aomJsFuncs property
AOM.AMG.userInputCreated = function (document) {
	return (AOM.AMG.userInput(document) != undefined);
}

AOM.AMG.userInput = function (document) {
   return AOM.documents.getAOMJsFuncsFromDoc(document).amgUserInput;
}

AOM.AMG.amgCreateGallerySection = function(document) {
	return AOM.documents.getAOMJsFuncsFromDoc(document).amgCreateGallerySection;
}


/* Any hit to app.document in is now considered a bug. Shout it out! */
AOM.AMG.designWindow = function (doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).designWindow();
}

AOM.AMG.updateStyleSection = function (doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).updateStyleSection();
}

AOM.AMG.updateImageOptionsSection = function (doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).updateImageOptionsSection();
}

AOM.AMG.updateCreateGallerySection = function (doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).updateCreateGallerySection();
}

AOM.AMG.updateCreateGalleryRadioButtons = function (hasSaveToDisk, doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).updateCreateGalleryRadioButtons(hasSaveToDisk);
}

AOM.AMG.loadStyles = function(doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).loadStyles();
}

AOM.AMG.userCustomizeStyle = function(id, doc) {
	return AOM.documents.getAOMJsFuncsFromDoc(doc).userCustomizeStyle(id);
}


AOM.AMG.createGallery = function (data)
{
	if (!data.valid)
		return;
	
	if (data.document.selections.length == 0) {
		AOM.alert(AOM.localize("$$$/AMG/javascript/pdfGenerator/noSelectThumbnail=No item is selected. Please select at least one item and try again."));
		return;
	}

	var galleryType = AOM.AmgPreviewSection.galleryType(data.document);
	var galleryCreator = new AOM.AmgGalleryCreator(galleryType, data, data.document.selections);

	/* Disallow task reentry */	
	if (galleryCreator.taskManager == undefined)
		return;

	if (galleryCreator.create())
		AOM.AmgUserInput.persist(data.document);
}


AOM.AMG.galleryMakerData = function(document)
{
    return AOM.documents.getAOMJsFuncsFromDoc(document).amgGalleryMakerData;
}

AOM.AMG.userFolder = function(document)
{
	if(document == undefined || !(document instanceof Document))
		AOM.alert("Undeterminable document: " + $.stack);
    return AOM.AMG.Paths.user + "document" + document.id + "/";
}


AOM.AmgDesignWindow = function(tabbedPalette, container, showCabinet)
{
    /*
     * AMG 2.0: No longer has its own tabbed palette.
     *
     * var tabbedPalette = AOM.AmgDesignWindow.create(document);
	 * tabbedPalette.visible = false; */
	tabbedPalette.content.populated = false;

	tabbedPalette.content.designGroup = container;
	tabbedPalette.content.maximumSize.height = 2000;
	tabbedPalette.content.designGroup.maximumSize.height = 2000;
	tabbedPalette.content.designGroup.document = tabbedPalette.content.document;

	AOM.AmgGalleryMaker.initialize();
	AOM.AmgDesignWindow.populate(tabbedPalette.content.designGroup, showCabinet);

	/* Work-around for #1840160 */
	AOM.AMG.userInput(tabbedPalette.content.document).window = tabbedPalette.content.window;
}
AOM.AmgDesignWindow.maximumSizeHeight = 10000;
AOM.AmgDesignWindow.create = function(document)
{
	var title = "Adobe Web Gallery";
	if (AOM.AMG.trackDocId)
		title += " ("+document.id+")";
	return AOM.AmgTabbedPalette.create(document, title, "amgDesign", "script", undefined);
}
AOM.AmgDesignWindow.populate = function (group, showCabinet)
{
	try
	{
		AOM.AMG.Tests.isGroup(group);
		group.orientation = "column";
		group.margins = 5;
		if (AOM.AMG.designWindowBackground != undefined)
		{
			var graphics = group.graphics;
			graphics.backgroundColor = graphics.newBrush(graphics.BrushType.SOLID_COLOR, this.background);
		}

		var currentUserInput = AOM.AMG.userInput(group.document);
		var template = currentUserInput.get("t_template");
		if (template == undefined)
		{
			template = AOM.AmgGalleryMaker.defaultTemplate();
			currentUserInput.set("t_template", template);
		}
		var styleOverwrite = false
		var style = currentUserInput.get("si_style");
		if (style == undefined)
		{
			style = AOM.AmgGalleryMaker.defaultStyle(group.document);
			currentUserInput.set("si_style", style);
			// if there was no style in the user input data store
			// make sure we the this styles values get loaded
			styleOverwrite = true;
		}

		var foldableSet;
		var customPanel;
		customPanel = new AOM.CustomPanel(group);
		if(!showCabinet) {
			group.headSectionGroup = customPanel.addHeaderSection(AOM.AmgHeaderResource, "header");
			foldableSet = customPanel.addAccordionSection();
			foldableSet.document = group.document;

			// Write foldableSet onClickFoldableSection callback
			foldableSet.onClickFoldableSection = function(openCloseButton) {
				var selectedSection = this.getSelectedSectionByName(openCloseButton.name);
				AOM.AMG.userInput(this.document).set("mgselectedSection", selectedSection);
			}
		} else {
			group.headSectionGroup = customPanel.addHeaderSection(AOM.AmgHeaderResource, "header", "bottom");
			foldableSet = customPanel.addCabinetSection();
			foldableSet.document = group.document;

			// Set foldableSet onClickFoldableSection callback
			foldableSet.onClickFoldableSection  = function(openCloseButton) {
				AOM.AMG.userInput(this.document).set(openCloseButton.name, openCloseButton.isOpen);
			}
		}

		var insertHeaderSection = function(resource) {
			return group.headSectionGroup.add(resource);
		}
		AOM.AmgTemplateSection.create(insertHeaderSection, template, group);
		AOM.AmgLoadStyleSection.create(insertHeaderSection, template, group);
		AOM.AmgPreviewSection.create(insertHeaderSection, group.document);

		var saveUploadButtonGroup = customPanel.addFooterSection(AOM.AmgCreateGallerySection.saveUploadButtonContents, "saveUpload", "top");
		saveUploadButtonGroup.document = group.document;
		AOM.AmgSaveUploadGroupEventHanldeInit(saveUploadButtonGroup);
		group.layout = new AOM.CustomPanelLayoutManager(group);

        group.document.aomJsFuncs.updateStyleSection = function() {
            foldableSet.removeAllFoldableSections();
        	var initialSectionName = AOM.AmgStyleSection.loadUi(foldableSet);
        	AOM.AmgCreateGallerySection.create(foldableSet);
		    AOM.AMG.updateCreateGallerySection(foldableSet.document);
		    AOM.theme(group.document).applyTheme(group, true);

		    if(!showCabinet) {
				//set open/close status
				var selectedSection = AOM.AMG.userInput(group.document).get("mgselectedSection");
				if (selectedSection == undefined || selectedSection.length == 0) {
					customPanel.accordionSection.selectedSection = initialSectionName;
				} else {
					if (AOM.Accordion.hasSectionName(customPanel.accordionSection, selectedSection)) {
						customPanel.accordionSection.selectedSection = selectedSection;
					} else {
						customPanel.accordionSection.selectedSection = initialSectionName;
					}
				}
			}
        }

		AOM.AmgTemplateSection.currentTemplate(foldableSet.document, template);
		/* Was a bug since if "styleOverwrite" is true, the user input will be
		 * updated while the UI does not change accordingly.
		 *
		 * AOM.AmgGalleryMaker.loadStyle(template, style, styleOverwrite); */
		if(styleOverwrite == true) {
			AOM.AmgStyleSection.currentStyle(group.document, style, styleOverwrite);
			currentUserInput.set("select_style", style);
		}
		AOM.AMG.updateCreateGallerySection(group.document);
		group.visible = true;
	}
	catch (e)
	{
		AOM.alert(e + ": " + $.stack);
		AOM.AMG.Log.writeError(e);
	}
}
AOM.AmgDesignWindow.defaultControlWidth = 260;
AOM.AmgDesignWindow.loadUi = function (uiItems, foldableSet)
{
	var customtext = undefined;
	var showExtensions = undefined;
	var captiondropdown = undefined;
	var customTextLabel = undefined;
	var add = function (item, group)
	{
		switch (item.type)
		{
		 case "checkbox":
			addCheckbox(item.attributes, group);
			break;
		 case "colorpicker":
			addColorpicker(item.attributes, group);
			break;
		 case "combobox":
			addCombobox(item.attributes, item.values, item.labels, group);
			break;
		 case "hrule":
			addHRule(item.attributes, group);
			break;
		 case "hslider":
			addHSlider(item.attributes, group);
			break;
		 case "label":
			addLabel(item.attributes, group);
			break;
		 case "spacer":
			//addSpacer(item.attributes, group);
			break;
		 case "textarea":
			addTextarea(item.attributes, group);
			break;
		 case "textinput":
			addTextinput(item.attributes, group);
			break;
		 default:
			AOM.AMG.Log.writeError("DesignWindow.loadUi - at default switch with " + item.type);
			break;
		}
	}
	var nop = function () {;} // nop function for attributes we do not support
	var addAttributes = function (attributes, attributeFunctions)
	{
		for (var a in attributes)
		{
			if (attributeFunctions[a] != undefined)
				attributeFunctions[a]();
			else
				AOM.AMG.Log.writeError(attributeFunctions._caller + " - unhandled attribute '" + a + "'");
		}
	}
	var addCheckbox = function (attributes, group)
	{

		var customGroup = group.add(
            "group{\
                alignment:['fill', 'center'], alignChildren:['left', 'center'], \
				" + attributes.id + ":Custom{\
					type:'customBoundedValue',\
					themeType:'customcheckbox', \
					preferredSize:[100, 18],\
				}\
			}"
         );
         
         var control = customGroup.children[0];
		control.alignment = "left";
		var attributeFunctions = {
			_caller: "addCheckbox",
			id: nop,
			label: function () {control.title = AOM.AMG.localize(attributes.label);},
			'ag:layout': nop,
			width: function () {control.preferredSize = [attributes.width, control.preferredSize.height];}
		};
		addAttributes(attributes, attributeFunctions);
		if (attributes.id == "showExtensions") {
			showExtensions = control;
			var state = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("showFileNames");
			if (state == "true" || state == "1") {
                showExtensions.enabled = showExtensions.gsEnabled = true;
            }
            else
                showExtensions.enabled = showExtensions.gsEnabled = false;
		}
		if (attributes.id != undefined)
		{
			var value = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get(attributes.id);
			if (value != undefined)
			{
				// when the user input store is loaded via persisted user input or an xml file,
				// it is a string. if the user changes the checkbox state, it becomes a boolean.
				// while "control.value = (value == true || value == 'true')" should do the trick,
				// the switch will let us know if there is some unexpected value type...
				switch (typeof value)
				{
				 case 'boolean':
					control.checked = value;
					break;
				 case 'string':
					control.checked = (value == "true" || value == "1"); // Do not try to assign a string. It does not work. I promise...
					break;
				 default:
					AOM.AMG.Log.writeError("addCheckbox - unknown value type ("+typeof value+")");
					control.checked = true; // or should it default to false?
					break;
				}
			}
			else
				control.checked = false;
                
                
			control.document = AOM.AmgDesignWindow.currentDocument;
			control.onMouseDown = function () {
				AOM.AMG.userInput(this.document).set(attributes.id, "" + this.checked);
				AOM.AMG.userCustomizeStyle(attributes.id, this.document);
				if (attributes.id == "showFileNames" && showExtensions != undefined) {
					if (this.checked)
						showExtensions.enabled = showExtensions.gsEnabled = true;
					else
						showExtensions.enabled = showExtensions.gsEnabled = false;
					}
                if (attributes.id == "caption") {
                	if (captiondropdown != undefined) {
	                	if (this.checked)
	                		captiondropdown.enabled = captiondropdown.gsEnabled = true;
	                	else
	                		captiondropdown.enabled = captiondropdown.gsEnabled = false;
	                	var selected = captiondropdown.selection.data;
	                	if (customtext != undefined) {
		                	if (selected == "Custom Text" && this.checked)
		                		customtext.enabled = true;
		                	else
		                		customtext.enabled = false;
		                }
		                if (customTextLabel != undefined) {
		                	if (selected == "Custom Text" && this.checked)
		                		customTextLabel.enabled = customTextLabel.gsEnabled = true;
		                	else
		                		customTextLabel.enabled = customTextLabel.gsEnabled = false;
		                }
		                
	                }
                }
            }
		}
    
        // finally add the wrapped object to the custom object
		var wrappedObject = new AOM.CustomCheckbox(control);
	}
	var addColorpicker = function (attributes, group)
	{
		var control = undefined;
		if (attributes.title == undefined)
		{
			var customGroup = group.add(
                "group{\
					alignment:['fill', 'center'], alignChildren:['left', 'center'], \
                    " + attributes.id + ":Custom{\
						type:'customBoundedValue',\
						themeType:'colorpnl', \
						preferredSize:[20, 20],\
					}\
                }"
			);
			var control = customGroup.children[0];
			var attributeFunctions = {
				_caller: "addColorpicker",
				id: nop,
				'ag:style': nop,
				title: nop
			};
			addAttributes(attributes, attributeFunctions);
            
			control.graphics.customBgColor = control.graphics.newBrush(
							control.graphics.BrushType.SOLID_COLOR,
							AOM.AMG.Colorpicker.rgb(
								AOM.AMG.Colorpicker.get(
									attributes.id,
									AOM.AmgDesignWindow.currentDocument)));
			if (attributes.id != undefined)
			{
				control.document = AOM.AmgDesignWindow.currentDocument;
				control.onMouseDown = function () {
					var newColor = AOM.AMG.Colorpicker.pick(
						AOM.AMG.Colorpicker.get(attributes.id, this.document));
					if(newColor != -1) {
						AOM.AMG.Colorpicker.set(attributes.id, newColor, this.document);
						this.graphics.customBgColor = this.graphics.newBrush(
							this.graphics.BrushType.SOLID_COLOR,
							AOM.AMG.Colorpicker.rgb(newColor));
						AOM.AMG.userCustomizeStyle(attributes.id, this.document);
						this.notify("onDraw");
					}
				}
			}
			
			var warppedObject = new AOM.CustomIconButton(control); 			 
		}
		else
		{
			// Lightroom specifies the colorpicker label in the text attribute
			// so we need to put the colorpicker and label in an hbox.
			// NOTE - there probably should be a way to have alternatives implemented
			// in (e.g.) flashgallery.jsxinc...
			var uiItems = new Array();
			uiItems.push({type: "hbox", children: [
				{type: "colorpicker", attributes: {id: attributes.id}},
				{type: "label", attributes: {text: attributes.title}}
			]});
			addUiItems(uiItems, group);
		}
	}
	var addCombobox = function (attributes, values, labels, group)
	{
		var control = group.add("dropdownlist");
		var attributeFunctions = {
			_caller: "addCombobox",
			id: nop,
			'ag:layout': nop,
			defaultData: nop,
			width: function () {
                control.preferredSize = [
                    ((attributes.width == undefined) ? 100 : attributes.width), 
                    ((attributes.height == undefined) ? 20 : attributes.height)
                ];
            },
		};
		addAttributes(attributes, attributeFunctions);
		var seperateLabels = (labels.length == 0 ? false : true);
		var defaultData = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get(attributes.id);
		if (defaultData == undefined)
			defaultData = attributes.defaultData;
		
		for (var i = 0; i < values.length; i++)
		{
			var label = undefined;
			var data = undefined;
			if (seperateLabels)
			{
				label = labels[i].title; // label is in its own array
				data = values[i];
			}
			else
			{
				label = values[i].label; // label and data are properties of the value
				data = values[i].data;
			}
			var item = control.add("item", AOM.AMG.localize(label));
			item.data = data;
			if (data == defaultData)
				item.selected = true;
		}
		if (attributes.id == "captiondropdown") {
			captiondropdown = control;
			var state = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("caption");
			if (state == "true") {
                captiondropdown.enabled = captiondropdown.gsEnabled = true;
            }
            else
                captiondropdown.enabled = captiondropdown.gsEnabled = false;
		}
		// Call UserInput.set with the data that corresponds to the combobox label selection.
		if (attributes.id != undefined) {
			control.document = AOM.AmgDesignWindow.currentDocument;
			control.onChange = function () {
                if (this.selection != null) {
                    AOM.AMG.userInput(this.document).set(attributes.id, this.selection.data);
                    if(AOM.AmgStyleSection.loadingUi != true)
                        AOM.AMG.userCustomizeStyle(attributes.id, this.document);
                    if (attributes.id == "captiondropdown") {
                    	if (customtext != undefined) {
		                	if (this.selection.data == "Custom Text")
		                		customtext.enabled = true;
		                	else
		                		customtext.enabled = false;
	                	}
	                	if (customTextLabel != undefined) {
		                	if (this.selection.data == "Custom Text")
		                		customTextLabel.enabled = customTextLabel.gsEnabled = true;
		                	else
		                		customTextLabel.enabled = customTextLabel.gsEnabled = false;
	                	}
	                }
                }
            }
        }
		if (control.items.length > 0)
		{
			if (control.selection == null)
				control.items[0].selected = true;
			control.onChange();
		}
	}
	var addHRule = function (attributes, group)
	{
		//control = group.add("panel", {alignment:'left', orientation:'row', preferredSize:[attributes.width, 0]});
		//control = group.add("panel", {x:0, y:0, width:attributes.width, height:0});
	/* DWR - the rule doesn't show and goofs the window height (scrollbar is affected...)
		control = group.add("panel");
		control.preferredSize = [AOM.AmgAccordionSection.accordionButtonWidth - 40, 0]; // DWR - constant width adjustment
		control.orientation = "row";
		control.alignment = "left";
	*/
	}
	var addHSlider = function (attributes, group)
	{
		/* Replace the ordinary ScriptUI Slider with the customized Numeric Stepper.
		 * ScriptUI slider causes Bridge dead-lock and customize its onDraw is
		 * damn difficult.
		var control = group.add("slider"); */

		var control = new AOM.AmgNumericStepper(group);
		control.alignment = ['left', 'center'];

		var attributeFunctions = {
			_caller: "addHSlider",
			id: nop,
			minimum: function () {
				control.setSlider({
					minvalue: attributes.minimum,
					maxvalue: attributes.maximum,
					stepdelta: 1,
					preferredSize:[
						((attributes.width == undefined) ? 100 : attributes.width), 
						((attributes.height == undefined) ? 20 : attributes.height)
					],
				});
            
				control.setEditText({preferredSize:[
					((attributes.etWidth == undefined) ? 25 : attributes.etWidth), 18]});
			},
			maximum: nop,
			// textLeft: function() {control.setHeadLabel({text:AOM.AMG.localize(attributes.textLeft)});},
			textRight: function() {control.setFootLabel({
				text:AOM.AMG.localize(attributes.textRight)
			});},
		}
		addAttributes(attributes, attributeFunctions);
		if (attributes.id != undefined) {
			control.document = AOM.AmgDesignWindow.currentDocument;
			
			if (attributes.id == "captionWidthPercentView") {
				var oldValue = AOM.AMG.userInput(control.document).get(attributes.id);
				if (oldValue == undefined) {
					oldValue = Number(attributes.minimum);
					AOM.AMG.userInput(control.document).set(attributes.id + "_display", oldValue / attributes.ratio);
					AOM.AMG.userInput(control.document).set(attributes.id, oldValue / attributes.ratio);
				} else {
					if (Number(oldValue) == 0) {
						oldValue = AOM.AMG.userInput(control.document).get(attributes.id + "_display");
					} else {
						// handle binding value issue.
						AOM.AMG.userInput(control.document).set(attributes.id + "_display", oldValue);
					}
					oldValue = Number(oldValue) * Number(attributes.ratio);
				}
				control.setValue(oldValue);
				
				control.onChange = function () {
					AOM.AMG.userInput(control.document).set(attributes.id + "_display", this.value / attributes.ratio);
					AOM.AMG.userInput(this.document).set(attributes.id, this.value / attributes.ratio);
					if(AOM.AmgStyleSection.loadingUi != true)
						AOM.AMG.userCustomizeStyle(attributes.id, this.document);
				}
			} else {
				var oldValue = AOM.AMG.userInput(control.document).get(attributes.id);
				if (oldValue == undefined) {
					oldValue = Number(attributes.minimum);
					AOM.AMG.userInput(control.document).set(attributes.id, oldValue / attributes.ratio);
				} else {
					oldValue = Number(oldValue) * Number(attributes.ratio);
				}
				control.setValue(oldValue);
				control.onChange = function () {
					AOM.AMG.userInput(this.document).set(attributes.id, this.value / attributes.ratio);
					if(AOM.AmgStyleSection.loadingUi != true)
						AOM.AMG.userCustomizeStyle(attributes.id, this.document);
				}
			}
			
		}

		/* 1.0 didn't load value from last session. Not correct.
		control.value = attributes.minimum;
		control.onChange(); */
	}
	var addLabel = function (attributes, group)
	{
		var control = group.add("statictext");
		var attributeFunctions = {
			_caller: "addLabel",
			fontWeight: nop,
			id: nop,
			'ag:layout': nop,
			'ag:style': nop,
			text: function () {control.text = AOM.AMG.localize(attributes.text); },
			width: function () {
				if(attributes.height == undefined)
					control.preferredSize = [attributes.width, control.preferredSize.height];
				else
					control.preferredSize = [attributes.width, attributes.height];
			},
			height: function () {
				if(attributes.width == undefined)
					control.preferredSize = [control.preferredSize.width, attributes.height];
				else
					control.preferredSize = [attributes.width, attributes.height];
			},
			alignment: function() {control.alignment = [attributes.alignment, "center"];}
		};
		control.alignment = ["left", "center"];
		addAttributes(attributes, attributeFunctions);
		// Note - some labels have an id. Do we need to do something with it?
		if (attributes.id == "customTextLabel") {
			customTextLabel = control;
			var state = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("caption");
			var selected = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("captiondropdown");
			if (state == "true" && selected == "Custom Text") {
                customTextLabel.enabled = customTextLabel.gsEnabled = true;
            }
            else
                customTextLabel.enabled = customTextLabel.gsEnabled = false;
		}
    
        if (control.preferredSize.height < 18)  
            control.preferredSize = [control.preferredSize.width, 18];
	}
	var addTextarea = function (attributes, group)
	{
		var width = attributes.width == undefined ? AOM.AmgDesignWindow.defaultControlWidth : attributes.width;
		var control = group.add("edittext", {x:0, y:0, width:width, height:attributes.height}, "", {multiline: true, borderless:true, scrolling:true});
		if (attributes.id != undefined)
		{
			var text = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get(attributes.id);
			control.text = (text == undefined ? "" : text);
			control.document = AOM.AmgDesignWindow.currentDocument;
			control.onChange = function () {
				AOM.AMG.userInput(this.document).set(attributes.id, this.text);
				AOM.AMG.userCustomizeStyle(attributes.id, this.document);
			}
		}
	}
	var addTextinput = function (attributes, group)
	{
		var width = attributes.width == undefined ? AOM.AmgDesignWindow.defaultControlWidth : attributes.width;
		var height = attributes.height == undefined ? 18 : attributes.height;
		var control = group.add("edittext", {x:0, y:0, width:width, height:height}, "", {multiline: false, borderless:true});
		var attributeFunctions = {
			_caller: "addTextinput",
			editable: nop,
			id: nop,
			'ag:layout': nop,
			maxChars: nop,
			maximum: nop,
			'ag:maximumLength': nop,
			minimum: nop,
			'ag:resizeToFitTextHeight': nop,
			validate: nop,
			width: nop
		};
		addAttributes(attributes, attributeFunctions);
		control.preferredSize = [(attributes.width == undefined ? AOM.AmgDesignWindow.defaultControlWidth : attributes.width), control.preferredSize.height];
		if (attributes.id == "customtext") {
			customtext = control;
			var state = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("caption");
			var selected = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get("captiondropdown");
			if (state == "true" && selected == "Custom Text") {
                customtext.enabled = true;
            }
            else
                customtext.enabled = false;
		}
		if (attributes.id != undefined)
		{
			var value = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get(attributes.id);
			if (value != undefined)
				control.text = value;
			else
				control.text = "";

			control.document = AOM.AmgDesignWindow.currentDocument;
			control.onChange = function () {
				var oldValue = AOM.AMG.userInput(this.document).get(attributes.id);
				var currentValue = (this.text == undefined) ? undefined : this.text.amgTrim();
				var valid = AOM.AMG.userInput(this.document).set(attributes.id, currentValue);

				if(!valid && oldValue != undefined) {
					this.text = oldValue;
					AOM.AMG.isValid = false;
				} else {
					AOM.AMG.userCustomizeStyle(attributes.id, this.document);
					AOM.AMG.isValid = true;
				}
			}
		}

		//TODO, add event listener if necessary
		if (attributes.keyboardListener != undefined) {
            if (attributes.keyboardListener == "number") {
                control.addEventListener('keydown', AOM.Keyboard.nonNegativeIntegerEditText);
            } 
        }
	}
	var addUiItems = function (viewList, group)
	{
		try
		{
			for (var i = 0; i < viewList.length; i++)
			{
				var vi = viewList[i]; // view item
				switch (vi.type)
				{
				 case "hbox":
				 case "vbox":
					var box = group.add("group");
					box.alignment = "left";
					box.maximumSize.height = 2000;
					box.orientation = (vi.type == "hbox" ? "row" : "column");
					if(vi.attributes != undefined) {
						if(vi.attributes.alignment != undefined)
							box.alignment = vi.attributes.alignment;
						if(vi.attributes.width != undefined)
							box.preferredSize.width = vi.attributes.width;
						if(vi.attributes.height != undefined)
							box.preferredSize.height = vi.attributes.height;
					}
					box.spacing = 6;

					addUiItems(vi.children, box);
					break;
				 default:
					add(vi, group);
					break;
				}
			}
		}
		catch (e)
		{
			AOM.alert(e);
			AOM.AMG.Log.writeError("DesignWindow.loadUi/addUitItems caught - " + e);
		}
	}
	var addUiSections = function(viewList, foldableSet)
	{
	    try
	    {
	    	AOM.AmgDesignWindow.currentDocument = foldableSet.document;
	    	var initialSectionName;
	        for(var i = 0; i < viewList.length; ++i) {
	            var vi = viewList[i];
	            var type = vi.attributes["ag:style"];
	            if(type == undefined)
	                continue;

	            var title = AOM.AMG.localize(vi.attributes["title"]);
	            var id = vi.attributes["id"];
	            if(initialSectionName == undefined)
	            	initialSectionName = id;
	            var group = foldableSet.addFoldableSection(AOM.AmgStyleSection.foldResourceContents, id, title);
	            group.maximumSize.height = 2000;
	            addUiItems(vi.children, group);

				// Set the open/close status
				AOM.AmgDesignWindow.setOpenCloseStatus(group.parent.parent);
	        }
	        AOM.AmgDesignWindow.currentDocument = undefined;
	        return initialSectionName;
        }
        catch(e)
        {
        	AOM.alert(e);
            AOM.AMG.Log.writeError("DesignWindow.loadUi/addUitSections caught - " + e);
        }
    }

	var initialSectionName = addUiSections(uiItems, foldableSet);
	return initialSectionName;
}


AOM.AmgDesignWindow.setOpenCloseStatus = function(group) {
	for (var i = 0; i < group.children.length; i++) {
		var child = group.children[i];
		if (child instanceof Group) {
			AOM.AmgDesignWindow.setOpenCloseStatus(child);
		} else {
			var name = child.name;

			if (name != undefined) {
				var type = child.type;
				if (child.themeType != undefined)  {type = child.themeType;}

				if (type.toLowerCase() == "openclosebtn") {
					var value = AOM.AMG.userInput(AOM.AmgDesignWindow.currentDocument).get(child.name);
					if(value == "true" || value == true || value == undefined) {
						child.isOpen = true;
					} else {
						child.isOpen = false;
					}
				}
			}
		}
	}
}

AOM.AmgTabbedPalette = function() {}
AOM.AmgTabbedPalette.create = function (document, title, id, type, url)
{
	var error = function (s) {return AOM.AMG.Log.writeError("AOM.AMG.TabbedPalette.create - " + s);}
	AOM.AMG.Tests.isDocument(document);

	var result = undefined;
	try
	{
		if (url != undefined)
			result = new TabbedPalette(document,  title, id, type, url);
		else
			result = new TabbedPalette(document,  title, id, type);
		if (result == undefined)
			return error("new TabbedPalette returned undefined");
		return result;
	}
	catch (e)
	{
		AOM.alert(e);
		return error("caught: " + e);
	}
}

AOM.AMG.Paths = {};
AOM.AMG.Paths.app = AOM.Paths.project + "/mediagallery/"; // TODO - change to "Media Gallery" in RIBS...
AOM.AMG.Paths.resources = AOM.AMG.Paths.app + "resources/";
AOM.AMG.Paths.templates = AOM.AMG.Paths.resources + "templates/";
AOM.AMG.Paths.scripts = AOM.AMG.Paths.resources + "scripts/";
AOM.AMG.Paths.images = AOM.AMG.Paths.resources + "images/";
AOM.AMG.Paths.user = AOM.Paths.userData + "/MediaGallery/";
AOM.AMG.Paths.log = AOM.Paths.userData + "/";
AOM.AMG.Paths.preview = AOM.AMG.Paths.user + "preview";
AOM.AMG.Paths.previewInBrowser = AOM.AMG.Paths.user + "previewInBrowser";
AOM.AMG.Paths.persistedUserData = AOM.AMG.Paths.user + "userInput.json";
AOM.AMG.Paths.persistedFTPPresetUserData = AOM.AMG.Paths.user + "ftpPresetUserInput.json";

AOM.AmgAccordionSection = {};
AOM.AmgAccordionSection.accordionButtonWidth = 300;
AOM.AmgAccordionSection.accordionButtonHeight = 20;

AOM.AmgTemplateSection = function() {}
AOM.AmgTemplateSection.currentTemplate = function (doc, template, refresh)
{
	var currentUserInput = AOM.AMG.userInput(doc);
	if (template != undefined)
	{
		refresh = (refresh != undefined) ? refresh : false;
		if (refresh)
		{
			currentUserInput.initialize();
		}
		// copy the template to the user input data store
		currentUserInput.set("t_template", template);
	    AOM.AmgGalleryMaker.loadTemplate(template, doc);
		// can we use the current style with this template?
	    //var style = currentUserInput.get("si_style");
	    var style = currentUserInput.get("select_style");
	    var styleList = AOM.AmgGalleryMaker.styleList(doc, template);
	    
	    var inStyleList = function(styleList, style)
	    {
			for (var i = 0; i < styleList.length; i++) {
				if(styleList[i].id == style)
					return true;
			}
			return false;
		}
	    
	    if (style == undefined) {
	    	style = AOM.AmgGalleryMaker.defaultStyle(doc);
		} else if (inStyleList(styleList, style) != true) {
			//style = AOM.AmgGalleryMaker.defaultStyle(doc); // no, so use the default template
			style = styleList[0].id; //use the first one.
			currentUserInput.set("select_style", style);
		}
		
		var custom = currentUserInput.get("si_style_custom");
		/*if (custom == "true")
			AOM.AmgStyleSection.currentStyle(doc, "customized", false);*/
		AOM.AmgUserInput.loadSizes(doc);
		AOM.AMG.loadStyles(doc);
	}
	return (currentUserInput.get("t_template"));
}
AOM.AmgTemplateSection.create = function (insertFunction, selectedTemplate, parent)
{
	var group = insertFunction(AOM.AmgTemplateSection.resource);
	var dropdown = group.templateDropdown;
	parent.templateDropdown = dropdown;
	AOM.AmgGalleryMaker.loadTemplateDropdown(dropdown, selectedTemplate);
    group.templateDropdown.preferredSize = [AOM.AmgDesignWindow.defaultControlWidth * 3 / 4, group.templateDropdown.preferredSize.height];
    dropdown.document = parent.document;
    var userInput = AOM.AMG.userInput(dropdown.document);
    dropdown.programSetSelected = false;
	dropdown.onChange = function ()
	{
		if(this.programSetSelected == true)
	        return;
		if (this.selection != null) { // sometimes we get called when the window is begin destroyed..
		    /* The new template should not have a "Custom" style */
		    userInput.set("si_style_custom", "false");
			AOM.AmgTemplateSection.currentTemplate(this.document, this.selection.template, false);
		}
		parent.layout.layout(true);
	}
	return "template";
}
AOM.AmgTemplateSection.resource = new String(
"Group \
 { \
	orientation: 'row', \
	alignment: 'right', \
	margins: [20, 5, 5, 6], \
	templateLabel: StaticText { \
    	alignment: ['right', 'center'], \
    	text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/template=Template:") + "', preferredSize:[-1, 18] \
      } \
    templateDropdown: DropDownList {preferredSize:[240, 22], alignment:['right', 'center']} \
 }"
);

AOM.AmgPreviewSection = function() {}
AOM.AmgPreviewSection.create = function (insertFunction, document)
{
	group = insertFunction(AOM.AmgPreviewSection.resource);
    
    var aBrowserPreviewButton = group.previewControls.browserPreviewButton;
	var aBrowserPreviewButtonWrapperObject = new AOM.CustomIconButton(aBrowserPreviewButton);
	aBrowserPreviewButton.onMouseDown = function ()
	{
		if (!AOM.AMG.checkEditTextValidOnMac()) return;
	 
		var f = function (index) { index.execute(); };
		var data = new AOM.PreviewFormData(false, f, document, AOM.AmgGalleryCreator.createModes.previewInBrowser);
		AOM.AMG.createGallery(data);
	}
	return "preview";
}
AOM.AmgPreviewSection.galleryType = function (doc)
{       
    if (AOM.AMG.galleryMakerData(doc).models.identifier == "com.adobe.wpg.templates.jardinePro")
    	return AOM.AmgGalleryCreator.galleryTypes.html;
    if (AOM.AMG.galleryMakerData(doc).models.identifier == "com.adobe.wpg.airtight.airtight")
    	return AOM.AmgGalleryCreator.galleryTypes.airtight;
    return AOM.AmgGalleryCreator.galleryTypes.flash;
}
AOM.AmgPreviewSection.resource = new String(
"group \
 { \
	orientation: 'column', \
	alignment: 'right', \
	margins: [20, 0, 55, 10], \
	previewControls: Group \
	{ \
		orientation: 'row', \
		alignment: ['left','top'], \
		browserPreviewButton: Custom { \
			type:'customBoundedValue',\
			themeType:'iconbutton',\
			helpTip:' " + AOM.localizeEsc("$$$/MediaGallery/JavaScript/previewInBrowserTip=Refresh and preview in browser, only 20 pictures in the front can be shown") + "', \
            text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/browserPreview=Preview in Browser") + "', \
            alignment:'left', \
            preferredSize: [145, 22] \
        } \
	} \
 }"
);
AOM.CurrentStyleGroup = undefined;
AOM.AmgLoadStyleSection = function() {}
AOM.AmgLoadStyleSection.create = function (insertFunction, selectedTemplate, parent)
{
	var group = insertFunction(AOM.AmgLoadStyleSection.resource);
	AOM.CurrentStyleGroup = group;
	var dropdown = group.styleDropdown;
	var saveButton = group.styleSaveBtn;
	var deleteButton = group.styleDeleteBtn;
	parent.styleDropdown = dropdown;
	parent.saveButton = saveButton;
	parent.deleteButton = deleteButton;
	//dropdown.preferredSize = [AOM.AmgDesignWindow.defaultControlWidth * 2 / 3, dropdown.preferredSize.height];
	dropdown.document = parent.document;
	saveButton.document = parent.document;
    deleteButton.document = parent.document;
    
	dropdown.setSelected = function(selected) {
	     var i;
	     var items = this.items;
	     this.programSetSelected = true;
	     for(i = 0; i < items.length; ++i)
	         if(items[i].style == selected) {
	             items[i].selected = true;
	             this.programSetSelected = false;
	             return;
	         }
	     this.programSetSelected = false;
    }

	parent.document.aomJsFuncs.loadStyles = function() {
	    AOM.AmgLoadStyleSection.loadStyles(dropdown, parent);
    }

    parent.document.aomJsFuncs.userCustomizeStyle = function(id) {
        /* Determine if the control with *id* is part of a style definition.
         * ID naming convention: <control ID> + "_style_Modified", agree with
         * that defined in AOM.AmgGalleryMaker.updateUserInputFromModels(). 
         * 
         * If the control just-changed is part of a style definition, change
         * the dropdown list display and the user input. We should not change
         * "si_style" since it is also used by gallery generation code, so
         * we use a new "si_style_display" entry. */
		var saveButton = dropdown.parent.styleSaveBtn;
    	var deleteButton = dropdown.parent.styleDeleteBtn;
		var selectionItem = dropdown.selection;
		if (selectionItem.style != "customized") {
			dropdown.add("separator", "", 0);
			var listItem = dropdown.add("item", AOM.localize("$$$/ContactSheet/javascript/title/CustomTemplate=Custom"), 0);
			listItem.style = "customized";

			AOM.AMG.userInput(parent.document).set("si_style_custom", "true");
			dropdown.setSelected("customized");
			AOM.AmgStyleSection.setButtons(saveButton, deleteButton, "", "customized");
		}
    }

	return "loadStyle";
}
AOM.AmgLoadStyleSection.resource = new String(
"Group \
 { \
	orientation: 'row', \
	alignment: 'right', \
	margins: [20, 0, 5, 6], \
	templateLabel: StaticText { \
		alignment: ['right', 'center'], \
		text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/style=Style:") + "', preferredSize:[-1, 18] \
	} \
	styleDropdown: DropDownList {preferredSize:[145, 22], alignment:['right', 'center']} \
	styleSaveBtn:IconButton{\
		text:'',\
		preferredSize:[15, 20],\
		normalImagePath:'" + AOM.Paths.images + "/new_normal.png" + "',\
		rolloverImagePath:'" + AOM.Paths.images + "/new_rollover.png" + "',\
		disableImagePath:'" + AOM.Paths.images + "/new_disable.png" + "',\
		themeType:'swapbutton',\
		helpTip:' " + AOM.localizeEsc("$$$/AMG/javascript/ftp/saveStyle=Save Style") + "', \
	},\
	styleDeleteBtn: IconButton{\
		text:'', \
		preferredSize:[15, 20],\
		normalImagePath:'" + AOM.Paths.images + "/delete_normal.png" + "',\
		rolloverImagePath:'" + AOM.Paths.images + "/delete_rollover.png" + "',\
		disableImagePath:'" + AOM.Paths.images + "/delete_disable.png" + "',\
		themeType:'swapbutton',\
		helpTip:' " + AOM.localizeEsc("$$$/AMG/javascript/ftp/deleteStyle=Delete Selected Style") + "', \
	},\
 }"
);
AOM.AmgStyleSection = function() {}
AOM.AmgStyleSection.create = function (foldableSet)
{
    var foldGroup = foldableSet.addFoldableSection(AOM.AmgStyleSection.foldResourceContents, "style", AOM.AMG.localize("$$$/MediaGallery/JavaScript/SectionTitle/StyleInformation=Style Information"));
	foldGroup.maximumSize.height = 2000;
	return foldGroup;
}
AOM.AmgStyleSection.setButtons = function(saveButton, deleteButton, template, style)
{
	if(style == "customized") {
		saveButton.gsEnabled = saveButton.enabled = true;
		deleteButton.gsEnabled = deleteButton.enabled = false;
		return;
	}
	if(AOM.AMG.styleIsDefault[template][style] != undefined) {
		deleteButton.gsEnabled = deleteButton.enabled = false;
	} else {
		deleteButton.gsEnabled = deleteButton.enabled = true;
	}
	saveButton.gsEnabled = saveButton.enabled = false;
}
AOM.AmgLoadStyleSection.updateStyle = function(document, parent)
{
	if (AOM.latestDocumentId == document.id) {
		return;
	}
	
	var userInput = AOM.AMG.userInput(document);
	var saveButton = parent.saveButton;
	var deleteButton = parent.deleteButton;
	var dropdown = parent.styleDropdown;
	var currentTemplate = AOM.AmgTemplateSection.currentTemplate(document);
	var styleList = AOM.AmgGalleryMaker.styleList(document, parent.templateDropdown.selection.template);
	var styles = AOM.AmgGalleryMaker.templates[currentTemplate].styles;
	var currentStyleDisplay = userInput.get("si_style_custom");
	var originStyle = userInput.get("si_style");
	var selectStyle = userInput.get("select_style");
	var template = userInput.get("t_template");
	dropdown.programSetSelected = true;
	dropdown.removeAll();
	
	var styleChanged = true;
	if (currentStyleDisplay == "true") {
		dropdown.add("separator", "", 0);	
		listItem = dropdown.add("item", AOM.localize("$$$/ContactSheet/javascript/title/CustomTemplate=Custom"), 0);
		listItem.style = "customized";
		listItem.selected = true;
		styleChanged = false;
	}
	
	if (selectStyle != undefined) {
		originStyle = selectStyle;
	}
	
	var listItem;
	for (var i = 0; i < styleList.length; i++) {
		if (styleList[i].id == "-") {
			listItem = dropdown.add("separator", "-");
		} else {
			listItem = dropdown.add("item", styleList[i].name);
			listItem.style = styleList[i].id;
			if(listItem.style == originStyle && currentStyleDisplay != "true") {
		    	listItem.selected = true;
		    	styleChanged = false;
		    }
		}
	}
	
	if (styleChanged == true)
		dropdown.items[0].selected = true;
		
	if (currentStyleDisplay != "true") {
		dropdown.programSetSelected = false;
		dropdown.onChange(true);
	} else {
		AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, "customized");
		dropdown.programSetSelected = false;
	}
}

AOM.AmgLoadStyleSection.loadStyles = function (dropdown, parent, finish)
{
    dropdown.onChange = undefined;
    dropdown.removeAll();
    var userInput = AOM.AMG.userInput(dropdown.document);
    var saveButton = dropdown.parent.styleSaveBtn;
    var deleteButton = dropdown.parent.styleDeleteBtn;
	var template = userInput.get("t_template");
	
	// add a dropdown with the current list of styles
	var styleList = AOM.AmgGalleryMaker.styleList(dropdown.document, template);
	if (styleList.length < 1) // don't show a style list if only one style. can this ever happen?
		return;
	
	dropdown.changing = false;
	var styles = AOM.AmgGalleryMaker.templates[template].styles;
	var currentStyleDisplay = userInput.get("si_style_custom");
	var originStyle = userInput.get("si_style");
	var selectStyle = userInput.get("select_style");
	if (selectStyle != undefined) {
		originStyle = selectStyle;
	}
	var listItem;
	if (currentStyleDisplay == "true") {
		dropdown.add("separator", "", 0);
		listItem = dropdown.add("item", AOM.localize("$$$/ContactSheet/javascript/title/CustomTemplate=Custom"), 0);
		listItem.style = "customized";
		listItem.selected = true;
		AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, "customized");
	}
	for (var i = 0; i < styleList.length; i++) {
		if (styleList[i].id == "-") {
			listItem = dropdown.add("separator", "-");
		} else {
			listItem = dropdown.add("item", styleList[i].name);
			listItem.style = styleList[i].id;
			if(listItem.style == originStyle && currentStyleDisplay != "true")
		    	listItem.selected = true;
		}
	}
	
	if (currentStyleDisplay != "true") {
		var max = dropdown.items.length;
		for (var i = 0; i < max; i++) {
			var result = AOM.AmgStyleSection.currentStyle(dropdown.document, selectStyle, true);
			if (result == "cannot open file" || result == "file is broken") {
				dropdown.programSetSelected = true;
				dropdown.remove(selectStyle);
				
				if(dropdown.items[0].type == "separator")
					dropdown.remove(0);
				
				dropdown.items[0].selected = true;
				selectStyle = dropdown.items[0].style;
				dropdown.programSetSelected = false;
			} else {
				break;
			}
		}
		AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, dropdown.selection.style);
	}
	else
		AOM.AmgStyleSection.currentStyle(dropdown.document, "customized", false);
	
	if (finish == true)
		return;
	dropdown.onChange = function (byDeleteStyle)
	{
	    if(this.programSetSelected == true)
	        return;
	    var userInput = AOM.AMG.userInput(dropdown.document);
	    var template = userInput.get("t_template");
	    var oldStyle = userInput.get("select_style");
		var newStyle = this.selection.style;
		if(newStyle == "customized") {
		    this.setSelected(newStyle);
		    return;
        }
        var isCustom = false;
        if(this.items[0].style == "customized") {
        	isCustom = true;
        	saveButton.gsEnabled = saveButton.enabled = false;
			userInput.set("si_style_custom", "false");
		}
		
		//AOM.AMG.Log.writeLine("AOM.AmgStyleSection.dropdown.onChange - new style is "+newStyle);
		// the upcoming call to currentStyle() will hammer this dropdown object. 
		// use schedule task if the object is needed past that point?
		if (byDeleteStyle != true) {
			var result = AOM.AmgStyleSection.currentStyle(this.document, newStyle, true);
			if (result == "cannot open file" || result == "file is broken") {
				dropdown.programSetSelected = true;
				dropdown.remove(newStyle);
				if(dropdown.items[0].type == "separator")
					dropdown.remove(0);
				for (var i = 0; i < dropdown.items.length; i++) {
					if (dropdown.items[i].style == oldStyle) {
						dropdown.items[i].selected = true;
						break;
					}
				}
				if (i == dropdown.items.length)
					dropdown.items[0].selected = true;
				dropdown.programSetSelected = false;
				newStyle = oldStyle;
				if (isCustom == true) {
					userInput.set("si_style_custom", "true");
					if (dropdown.items[2].type == "separator")
						dropdown.remove(2);
					dropdown.items[0].selected = true;
				}
				if (result == "cannot open file")
					AOM.alert(AOM.localizeWithArgs("$$$/AMG/javascript/template/cannotLoadStyle=Can not load the style file caused by system error."));
				else
					AOM.alert(AOM.localizeWithArgs("$$$/AMG/javascript/template/loadStyleError=Can not load the style file because the file is broken."));
			} else if (isCustom == true) {
				this.programSetSelected = true;
				this.items[0].selected = true;
				this.remove(0);
				this.remove(0);
				for (var i = 0; i < this.items.length; i++) {
					if(this.items[i].style == newStyle)
						this.items[i].selected = true;
				}
				this.programSetSelected = false;
			}
		} else {
			var max = dropdown.items.length;
			for (var i = 0; i < max; i++) {
				var result = AOM.AmgStyleSection.currentStyle(this.document, newStyle, true);
				if (result == "cannot open file" || result == "file is broken") {
					dropdown.programSetSelected = true;
					dropdown.remove(newStyle);
					
					if(dropdown.items[0].type == "separator")
						dropdown.remove(0);
					
					dropdown.items[0].selected = true;
					newStyle = dropdown.items[0].style;
					dropdown.programSetSelected = false;
				} else {
					break;
				}
			}
		}
		userInput.set("select_style", newStyle);
		if (userInput.get("si_style_custom") != "true")
			AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, newStyle);
		else
			AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, "customized");
		parent.layout.layout("true");
	}
	saveButton.onClick = function()
	{
		var userInput = AOM.AMG.userInput(this.document);
		openSaveDialog = function() {
			var saveDialog = new Window("dialog", AOM.localize("$$$/AMG/javascript/title/styleTitle=New Style"), undefined);
			var sdGroup = saveDialog.add(
			"group{\
				orientation:'column',\
				nameGroup:Group{\
					alignment:['right', 'center'], \
					st:StaticText{text:'" + AOM.localizeEsc("$$$/AMG/javascript/title/styleNameLabel=Style Name:") + "', preferredSize:[-1, 18]},\
					edt:EditText{text:'', preferredSize:[160, 20]},\
				},\
				btnGroup:Group{\
					alignment:['right', 'center'],\
					createBtn:Button{text:'" + AOM.localizeEsc("$$$/AMG/javascript/title/createStyleButton=Create") + "'},\
					cancelBtn:Button{text:'" + AOM.localizeEsc("$$$/AMG/javascript/title/cancelStyleButton=Cancel") + "'},\
				},\
			}\
			");
			
			saveDialog.defaultElement = sdGroup.btnGroup.createBtn;
			saveDialog.cancelElement = sdGroup.btnGroup.cancelBtn;
			sdGroup.nameGroup.edt.active = true;
		
			sdGroup.btnGroup.cancelBtn.onClick = function() {
				saveDialog.hasCanceled = true;
				saveDialog.close();
			}
			sdGroup.btnGroup.createBtn.onClick = function() {
				var presetName = this.parent.parent.nameGroup.edt.text.amgTrim();
				var templateName = userInput.get("t_template");
				if (presetName == undefined || presetName.length == 0) {
					AOM.alert(AOM.localize("$$$/AMG/javascript/title/emptyStyleName=Style name is required, please input style name."));
					return;
				}
				if (!AOM.CS.Validation.isTemplateName(presetName)) {
					AOM.alert(AOM.localize("$$$/AMG/javascript/title/illegalStyleName=Style name includes illegal characters, please input style name again."));
					return;
				}
				if(presetName.length > 30) {
					AOM.alert(AOM.localize("$$$/AMG/javascript/title/tooLongStyleName=Style name is too long, please input style name again."));
					return;
				}
				for (var i = 0; i < dropdown.items.length; i++) {
					if (dropdown.items[i].type == "separator")
						continue;
					var styleName = dropdown.items[i].style;
					if (presetName.toLowerCase() == styleName.toLowerCase()) {
						if(AOM.AMG.styleIsDefault[templateName][styleName] != undefined) {
							AOM.alert(AOM.localize("$$$/AMG/javascript/title/duplicateWithPreset=The name is the same as a preset style, please input another one."));
							return;
						} else {
							if(!AOM.confirm(AOM.localize("$$$/AMG/javascript/title/duplicateStyleName=The name is the same as an existent one, \nreplace it?"))) {
								return;
							}
							dropdown.remove(styleName);
							var filePath = AOM.AMG.Paths.persistUserStylePath + templateName + "/" + styleName + ".json";
							var file = new File(filePath);
							file.remove();
						}
					}
				}
				
				saveDialog.hasCanceled = false;
				saveDialog.presetName = presetName;
				saveDialog.close();
			}
			saveDialog.show();
		
			return saveDialog;
		}
		this.gsEnabled = this.enabled = false;
		var saveDialog = openSaveDialog();
		if (saveDialog.hasCanceled || saveDialog.presetName == undefined) {
			this.gsEnabled = this.enabled = true;
		 	return; 
		}
		
		var newPresetName = saveDialog.presetName;
		
		dropdown.remove(0);
		dropdown.remove(0);
		var template = userInput.get("t_template");
		if(AOM.AMG.styleIsDefault[template][dropdown.items[0].style] != undefined){
			dropdown.add("separator", "", 0);
		}
		
		dropdown.programSetSelected = true;
		var newItem = dropdown.add("item", newPresetName, 0);
		newItem.style = newPresetName;
		newItem.selected = true;
		
		AOM.AmgStyleSection.setButtons(this, deleteButton, template, newPresetName);
		
		dropdown.programSetSelected = false;
		userInput.set("si_style_custom", "false");
		userInput.set("select_style", newPresetName);
		
		var data = userInput.data;
		AOM.AmgUserInput.persistUserStyle(template, newPresetName, this.document);
	}
	deleteButton.onClick = function()
	{
		var userInput = AOM.AMG.userInput(this.document);
		var template = userInput.get("t_template");
		var style = dropdown.selection.style;
		this.gsEnabled = this.enabled = false;
		if(!AOM.confirm(AOM.localize("$$$/AMG/javascript/title/deleteTemplate=Do you really want to delete the template?"))) {
			this.gsEnabled = this.enabled = true;
			return;
		}
		var filePath = AOM.AMG.Paths.persistUserStylePath + template + "/" + style + ".json";
		var file = new File(filePath);
		file.remove();
		
		dropdown.programSetSelected = true;
		dropdown.remove(style);
		if(dropdown.items[0].type == "separator")
			dropdown.remove(0);
		
		dropdown.items[0].selected = true;
		dropdown.programSetSelected = false;
		dropdown.onChange(true);
	}
}
AOM.AMG.styleIsDefault = {
	"01default_st":
	{
		"mediumThumbnail.xml":"true",
		"smallThumbnail.xml":"true"
	},
	"02filmstrip_vert_mt":
	{
		"largeThumbnail.xml":"true",
		"mediumThumbnail.xml":"true"
	},
	"03filmstrip":
	{
		"05darkroom.xml":"true"
	},
	"04journal_filmstrip":
	{
		"05darkroom.xml":"true"
	},
	"05journal_ss":
	{
		"05darkroom.xml":"true"
	},
	"06slideshow":
	{
		"05darkroom.xml":"true"
	},
	"07lightroomgallery":
	{
		"01default.xml":"true",
		"02bluesky.xml":"true",
		"03classic.xml":"true",
		"04earlgrey.xml":"true",
		"05mossyrock.xml":"true",
		"06nightlife.xml":"true",
		"07paperwhite.xml":"true",
		"08slideshow.xml":"true",
		"09theblues.xml":"true",
		"10warmday.xml":"true"
	},
	"08htmlgallery":
	{
		"01lightroom.xml":"true"
	},
	"09postcardviewer":
	{
		"01lightroom.xml":"true"
	},
	"10autoviewer":
	{
		"01lightroom.xml":"true"
	},
	"11simpleviewer":
	{
		"01lightroom.xml":"true"
	}
}
AOM.AmgStyleSection.currentStyle = function (doc, style, overwrite)
{
	var saveButton = AOM.CurrentStyleGroup.styleSaveBtn;
	var deleteButton = AOM.CurrentStyleGroup.styleDeleteBtn;
	var currentUserInput = AOM.AMG.userInput(doc);
	if (style != undefined)
	{
	    // if we are given a style, copy it to the user input data store
		// and then update the style section
		var template = currentUserInput.get("t_template");
		if (template == undefined)
			return AOM.AMG.Log.writeError("AOM.AmgStyleSection.currentStyle - could not get template");

		if(style != "customized") {
		    
		    if(AOM.AMG.styleIsDefault[template][style] == undefined) {
				var folderPath = AOM.AMG.Paths.persistUserStylePath + template + "/";
				var filePath = folderPath + style + ".json";
				var file = new File(filePath);
				
				if (!file.open("r")) {
					return "cannot open file";
				} else {
					file.seek(6,2);
					var end = file.readln();
					file.seek(4,2);
					var end2 = file.readln();
					if (end != "];" && end2 != "];") {
						file.close();
						file.remove();
						return "file is broken";
					}
					file.seek(0);
					var json = file.read();
				    file.close();
				    try {
				    	eval(json);
				    } catch (e) {
						file.remove();
				    	return "file is broken";
					}
				    var data = AOM.AmgUserInput.userSavedStyle;
				}
				var originStyle;
				for (var i = 0; i < data.length; i++) {
					if (data[i].id == "si_style") {
						originStyle = data[i].value;
						break;
					}
				}
				if (originStyle == undefined) {
					return AOM.AMG.Log.writeError("AOM.AmgStyleSection.currentStyle - could not get style");
				}
				AOM.AmgGalleryMaker.updateUserInputFromDefaults(true, doc);
				AOM.AmgGalleryMaker.loadStyle(template, originStyle, overwrite, doc);
				
				for (var i = 0; i < data.length; i++) {
					var field = data[i];
					currentUserInput.set(field.id, File.decode(field.value));
				}
			} else {
				AOM.AmgGalleryMaker.updateUserInputFromDefaults(true, doc);
				AOM.AmgGalleryMaker.loadStyle(template, style, overwrite, doc);
				currentUserInput.set("si_style", style);
			}
			
			AOM.AmgStyleSection.setButtons(saveButton, deleteButton, template, style);
		    
		    //here we should load template ui infomation to userInput, because when change a userStyle to a preset one,
		    //the ui default value that not defined in style file but defined in template file can't be reloaded,
		    //so the display is not correctly.
		} else {
			currentUserInput.restore();
			var originStyle = currentUserInput.get("si_style");
			if (originStyle == undefined) {
				return AOM.AMG.Log.writeError("AOM.AmgStyleSection.currentStyle - could not get style");
			}
			AOM.AmgGalleryMaker.updateUserInputFromDefaults(true, doc);
			AOM.AmgGalleryMaker.loadStyle(template, originStyle, overwrite, doc);
			currentUserInput.restore();
		}
		
		AOM.AMG.updateStyleSection(doc);
	}
	// return the user input style
	return currentUserInput.get("si_style");
}
AOM.AmgStyleSection.loadUi = function (foldableSet)
{
    var amgGalleryMakerData = AOM.AMG.galleryMakerData(foldableSet.document);

    /* loadingUi is the indicator that prevent the dropdown list onChange
     * event during the UI loading. */
    AOM.AmgStyleSection.loadingUi = true;
	var initialSectionName = AOM.AmgDesignWindow.loadUi(amgGalleryMakerData.views, foldableSet);
	AOM.AmgStyleSection.loadingUi = false;

	return initialSectionName;
}
AOM.AmgStyleSection.foldResourceContents = new String(
"group \
 { \
	orientation: 'column', \
		alignment: 'left', \
		margins: 5 \
 }"
);
/* AMG 1.0 Code: AMG 2.0 REMOVE
 *     Image Option Section is now fully defined in gallerymaker.xml.
AOM.AmgImageOptionsSection = function() {}
AOM.AmgImageOptionsSection.create = function (insertFunction)
{
	var group = insertFunction(AOM.AmgImageOptionsSection.foldResourceContents, "imageOption", AOM.AMG.localize("$$$/MediaGallery/JavaScript/SectionTitle/ImageOptions=Image Options"));
	app.document.aomJsFuncs.updateImageOptionsSection = function()
	{
		var sizeDropdown = function(id, label)
		{
			var combobox = {type: "combobox", "attributes": {id: id, defaultData: "medium"}, values: new Array(), labels: new Array()};
			combobox.values.push({label: AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsExtraLarge=Extra large"), data: "extraLarge"});
			combobox.values.push({label: AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsLarge=Large"), data: "large"});
			combobox.values.push({label: AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsMedium=Medium"), data: "medium"});
			combobox.values.push({label: AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsSmall=Small"), data: "small"});
			var hbox = {type: "hbox", attributes: {verticalAlign: "middle"}, children: new Array()};
			hbox.children.push({type: "label", attributes: {text: label, width: 75}});
			hbox.children.push(combobox);
			return hbox;
		}
		var uiItems = new Array();
		uiItems.push(sizeDropdown("io_preview", AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsPreview=Preview Size:")));
		if (AOM.AmgPreviewSection.galleryType() != AOM.AmgGalleryCreator.galleryTypes.html)
			uiItems.push(sizeDropdown("io_thumbnail", AOM.AMG.localize("$$$/MediaGallery/JavaScript/Label/ImageOptionsThumbnail=Thumbnail Size:")));
		while (group.children.length)
		{
			group.remove(0);
		}
		AOM.AmgDesignWindow.loadUi(uiItems, group);
	}
}
AOM.AmgImageOptionsSection.foldResourceContents = new String(
"group \
 { \
    orientation: 'column' , \
	alignment: 'left', \
	margins: 5 \
 }"
); */

AOM.AmgCreateGallerySection = function() {}
AOM.AmgCreateGallerySection.hasProgramInteract = false;
AOM.AmgCreateGallerySection.setEnabledProps = function(group, enabled, doc) {
	for (var i = 0; i < group.children.length; i++) {
		var child = group.children[i];
		if (child instanceof Group) {
			AOM.AmgCreateGallerySection.setEnabledProps(child, enabled, doc);
		} else {
			if (child.type == "edittext") {
				child.gsEnabled = child.enabled = enabled;
				var theme = AOM.theme(doc);
				theme.setEditTextDisableBgColor(child);
			} else {
				child.gsEnabled = child.enabled = enabled;
			}
		}
	}
}
AOM.AmgCreateGallerySection.getListIndexByText = function(ddl, keyword, hasCaseSensitive) {
		if (hasCaseSensitive == undefined) hasCaseSensitive = false;
		var index = -1;
		var items = ddl.items;
		if (!hasCaseSensitive) {keyword = keyword.toLowerCase();}
		for (var i = 0; i < items.length; i++) {
			var text = items[i].text;
			if (!hasCaseSensitive) {
				text = text.toLowerCase();
			}
			if (text == keyword) {
				index = i;
			}
		}
		return index;
	}
AOM.AmgCreateGallerySection.loadDataToFTPDropDownList = function(ftpDropDownList, userInput) {
	if(userInput == undefined)
		AOM.alert("Undefined User Input: " + $.stack);

	AOM.AmgCreateGallerySection.hasProgramInteract = true;
	//Get the default selected value from userInput file.
	var defaultSelectedValue = userInput.get("cg_ftpTemplate");

	ftpDropDownList.removeAll();
	ftpDropDownList.add("item", AOM.localize("$$$/AMG/javascript/ftp/presetCustom=Custom"));
	ftpDropDownList.add("separator", "-");
	ftpDropDownList.selection = 0;

	var ftpPresetItems = AOM.AMG.ftpPresetUserInput().getItems();
	for(var idx = 0; idx <ftpPresetItems.length; idx++) {
		var itm = ftpPresetItems[idx];
		var newItem = ftpDropDownList.add("item", itm.id);
		if (defaultSelectedValue == itm.id) {
			ftpDropDownList.selection = newItem;
		}
	}
	if (ftpDropDownList.selection.text != defaultSelectedValue) {
		userInput.set(ftpDropDownList.name, ftpDropDownList.selection.text);
	}
	AOM.AmgCreateGallerySection.hasProgramInteract = false;
}
AOM.AmgCreateGallerySection.loadDataToFTPGroup = function(group, userInput) {
	var isEmpty = function(s) {
		return (s== undefined || s.length == 0);
	}
	var strToBoolean = function(s) {
		if (s == undefined) return false;
		if (s == "true") 
			return true;
		else 
			return false;
	}

	for (var i = 0; i < group.children.length; i++) {
		var child = group.children[i];
		if (child instanceof Group) {
			AOM.AmgCreateGallerySection.loadDataToFTPGroup(child, userInput);
		} else {
			var name = child.name;
			if (name != undefined) {
				var type = child.type;
				var value =userInput.get(child.name);
				switch(type.toLowerCase()) {
				case "checkbox" :
					if (isEmpty(value)) {
						child.value = false;
						userInput.set(child.name, child.value.toString());
					} else {
						child.value = strToBoolean(value);
					}
					break;
				case "edittext" :
					if (isEmpty(value)) {
						var defaultValue = (child.defaultValue == undefined ? "" : child.defaultValue);
						child.text = defaultValue;
						userInput.set(child.name, child.text);
					} else {
						if (name == "cg_userNameText")
							value = AOM.AmgCreateGallerySection.decryptUsername(value);
						child.text = value;
					}
					break;
				case "dropdownlist" :
					AOM.AmgCreateGallerySection.loadDataToFTPDropDownList(child, userInput);
					break;
				}
			}
		}
	}
}
AOM.AmgCreateGallerySection.encryptPassword = function(passwd)
{
	if (AOM.AMG.WebAccess.externalObject == undefined) {
		AOM.AMG.WebAccess.open();
	}
	var ftpConnection = new FtpConnection();
	ftpConnection.password = passwd;
	var value = ftpConnection.encryptedPassword;
	ftpConnection = null;
	return value;
}
AOM.AmgCreateGallerySection.encryptUsername = function(username)
{
	if (AOM.AMG.WebAccess.externalObject == undefined) {
		AOM.AMG.WebAccess.open();
	}
	var ftpConnection = new FtpConnection();
	ftpConnection.username = username;
	var value = ftpConnection.encryptedUsername;
	ftpConnection = null;
	return value;
}
AOM.AmgCreateGallerySection.decryptUsername = function(username)
{
	if (AOM.AMG.WebAccess.externalObject == undefined) {
		AOM.AMG.WebAccess.open();
	}
	var ftpConnection = new FtpConnection();
	ftpConnection.encryptedUsername = username;
	var value = ftpConnection.username;
	ftpConnection = null;
	return value;
}
AOM.AmgCreateGallerySection.addItemInfoFromFTPGroup = function(newItem, group) {
	for (var i = 0; i < group.children.length; i++) {
		var child = group.children[i];	
		if (child instanceof Group) {
			AOM.AmgCreateGallerySection.addItemInfoFromFTPGroup(newItem, child);
		} else {
			var name = child.name;
			if (name != undefined) {
				var value = undefined;
				var type;
				if (child.themeType == undefined)
					type = child.type;
				else
					type = child.themeType;
				switch(type.toLowerCase()) {
					case "edittext" :
						if (name == "cg_userNameText")
							value = AOM.AmgCreateGallerySection.encryptUsername(child.text);
						else
							value = child.text;
						break;
					case "checkbox" :
						value = child.value;
						break;
					case "customcheckbox" :
						value = child.checked;
						break;
					default:
						break;
				}
				if (value != undefined) {
					newItem[name] = value;
				}
			}
		}
	}
}
AOM.AmgCreateGallerySection.persistFTPGroupValues = function(group, userInput) {
	for (var i = 0; i < group.children.length; i++) {
		var child = group.children[i];	
		if (child instanceof Group) {
			AOM.AmgCreateGallerySection.persistFTPGroupValues(child, userInput);
		} else {
			var name = child.name;
			if (name != undefined) {
				var type;
				if (child.themeType == undefined)
					type = child.type;
				else
					type = child.themeType;
					
				switch(type.toLowerCase()) {
				case "customcheckbox" :
					userInput.set(child.name, child.checked);
					break;
				case "checkbox" :
					userInput.set(child.name, child.value.toString());
					break;
				case "edittext" :
					if (child.name == "cg_userNameText")
						userInput.set(child.name, AOM.AmgCreateGallerySection.encryptUsername(child.text));
					else
						userInput.set(child.name, child.text);
					break;
				}
			}
		}
	}
}
AOM.AmgCreateGallerySection.openSaveDialog = function() {
	var saveDialog = new Window("dialog", AOM.localize("$$$/AMG/javascript/ftp/presetTitle=New Preset"), undefined);
	var sdGroup = saveDialog.add(
	"group{\
		orientation:'column',\
		nameGroup:Group{\
			alignment:['right', 'center'], \
			st:StaticText{text:'" + AOM.localizeEsc("$$$/AMG/javascript/ftp/presetNameLabel=Preset Name:") + "', preferredSize:[-1, 18]},\
			edt:EditText{text:'', preferredSize:[160, 20]},\
		},\
		btnGroup:Group{\
			alignment:['right', 'center'],\
			createBtn:Button{text:'" + AOM.localizeEsc("$$$/AMG/javascript/ftp/createPresetButton=Create") + "'},\
			cancelBtn:Button{text:'" + AOM.localizeEsc("$$$/AMG/javascript/ftp/cancelPresetButton=Cancel") + "'},\
		},\
	}\
	");
		
	saveDialog.defaultElement = sdGroup.btnGroup.createBtn;
	saveDialog.cancelElement = sdGroup.btnGroup.cancelBtn;
	sdGroup.nameGroup.edt.active = true;

	sdGroup.btnGroup.cancelBtn.onClick = function() {
		saveDialog.hasCanceled = true;
		saveDialog.close();
	}
	sdGroup.btnGroup.createBtn.onClick = function() {
		var presetName = this.parent.parent.nameGroup.edt.text.amgTrim();
		if (presetName == undefined || presetName.length == 0) {
			AOM.alert(AOM.localize("$$$/AMG/javascript/ftp/emptyPresetName=Preset Name is required, please input preset name."));
			return;
		}
		if(presetName.length > 255) {
			AOM.alert(AOM.localize("$$$/AMG/javascript/ftp/tooLongPresetName=Preset Name is too long, please input preset name again."));
			return;
		}
		
		saveDialog.hasCanceled = false;
		saveDialog.presetName = presetName;
		saveDialog.close();
	}
	saveDialog.show();

	return saveDialog;
}

AOM.AmgCreateGallerySection.create = function (foldableSet)
{
	var group = foldableSet.addFoldableSection(AOM.AmgCreateGallerySection.foldResourceContents, "createGallery", AOM.AMG.localize("$$$/MediaGallery/JavaScript/SectionTitle/CreateGallery=Create Gallery"));
	
	//Set the open/close status
	AOM.AmgDesignWindow.currentDocument = foldableSet.document;
	AOM.AmgDesignWindow.setOpenCloseStatus(group.parent.parent);
	AOM.AmgDesignWindow.currentDocument = undefined;
	
	foldableSet.document.aomJsFuncs.amgCreateGallerySection = group;

	foldableSet.document.aomJsFuncs.updateCreateGallerySection = function() {
		var userInput = AOM.AMG.userInput(foldableSet.document);
		
		//init radiobuttons
		var save = userInput.get("cg_saveRadioButton");
		
		//init edittext and checkbox
		group.galleryText.defaultValue = "Adobe Web Gallery";
		AOM.AmgCreateGallerySection.loadDataToFTPGroup(group, userInput);
	}

	group.galleryText.document = foldableSet.document;
	group.galleryText.onChange = function () {
		var currentUserInput = AOM.AMG.userInput(this.document);
		var isValid = currentUserInput.set("cg_galleryText", this.text);
		if (isValid) {
			AOM.AMG.isValid = true;
		} else {
			this.text = currentUserInput.get("cg_galleryText");
			AOM.AMG.isValid = false;
		}
	}

	group.saveGroup.saveFolderText.document = foldableSet.document;
	group.saveGroup.saveFolderText.onChange = function ()
	{
		AOM.AMG.userInput(this.document).set("cg_saveFolderText", this.text);
	}

	var saveBrowseButton = group.saveGroup.saveLocationGroup.saveBrowseButton;
 	var warppedSaveBrowseButtonObject = new AOM.CustomIconButton(saveBrowseButton); 
	saveBrowseButton.onMouseDown = function ()
	{
		var folder = Folder.selectDialog(AOM.AMG.localize("$$$/MediaGallery/JavaScript/SelectLocation=Select location for Adobe Web Gallery"));
		if (folder == null) return;
		
		group.saveGroup.saveFolderText.text = folder.fsName;
		group.saveGroup.saveFolderText.onChange();
	}
	
	var uploadInfoChange = function(ele) {
		if (ele.type.toLowerCase() == "edittext") {
			if (ele.name == "cg_userNameText") {
				AOM.AMG.userInput(foldableSet.document).set(
					ele.name,
					AOM.AmgCreateGallerySection.encryptUsername(ele.text)
				);
			} else {
                if (ele.name == "cg_passwordText")
                    ele.text = AOM.AmgCreateGallerySection.encryptPassword(ele.text);
                AOM.AMG.userInput(foldableSet.document).set(ele.name, ele.text);
			}
         } else if (ele.type.toLowerCase() == "customboundedvalue") {
			if (ele.themeType != undefined && ele.themeType.toLowerCase() == "customcheckbox")
				AOM.AMG.userInput(foldableSet.document).set(ele.name, ele.checked.toString());
		} else {
			AOM.AMG.userInput(foldableSet.document).set(ele.name, ele.value.toString());
		}
	
		AOM.AmgCreateGallerySection.hasProgramInteract = true;
		var ftpDropDownList = group.ftpGroup.tGroup.ftpTemplate;
		ftpDropDownList.selection = ftpDropDownList.items[0];
		AOM.AmgCreateGallerySection.hasProgramInteract = false;
	}
	group.ftpGroup.ftpServerText.onChange = function () {
		uploadInfoChange(this);
	}
	group.ftpGroup.nameGroup.userNameText.onChange = function () {
		uploadInfoChange(this);
	}
	group.ftpGroup.passGroup.passwordText.addEventListener ("focus",
		function() {
			this.text = "";
			AOM.AMG.userInput(foldableSet.document).set("cg_passwordText", "");
		});
	group.ftpGroup.passGroup.passwordText.onChange = function () {
		uploadInfoChange(this);
	}
	group.ftpGroup.foldGroup.uploadFolderText.onChange = function () {
		uploadInfoChange(this);
	}

    var ftpHasSavePass = group.ftpGroup.cpassGroup.ftpHasSavePass;
	ftpHasSavePass.checked = AOM.AMG.getUserInputDataOfCustomCheckbox(foldableSet.document, ftpHasSavePass);
	ftpHasSavePass.onMouseDown = function() {
		uploadInfoChange(this);
	}
	var warppedObject = new AOM.CustomCheckbox(ftpHasSavePass);

	//FTP Preset event-handlers.
	group.ftpGroup.tGroup.ftpSaveBtn.document = foldableSet.document;
	group.ftpGroup.tGroup.ftpSaveBtn.onClick = function() {
		if (!AOM.AMG.checkEditTextValidOnMac()) return;
		var currentUserInput = AOM.AMG.userInput(this.document);
		var data = new AOM.UploadFormData(
						currentUserInput.get("cg_galleryText"), currentUserInput.get("cg_ftpServerText"),
						currentUserInput.get("cg_userNameText"), currentUserInput.get("cg_passwordText"), 
						currentUserInput.get("cg_uploadFolderText"), this.document);												
		if (!data.valid) return;

		//call save dialog
		var saveDialog = AOM.AmgCreateGallerySection.openSaveDialog();
		if (saveDialog.hasCanceled) { return; }
		var newPresetName = saveDialog.presetName;

		//check is duplicate
		var duplicateIndex = AOM.AMG.ftpPresetUserInput().indexOf(newPresetName);
		if (duplicateIndex >= 0) {
			if (!AOM.confirm(AOM.localize(
				"$$$/AMG/javascript/ftp/duplicateFTPInfo=The specified preset already exists. Do you want to overwrite it?"))) {
				return;
			}
		}

		//check has save pass?
		var ftpGroup = this.parent.parent.parent.ftpGroup;
		if (!ftpGroup.cpassGroup.ftpHasSavePass.checked) {
			currentUserInput.set("cg_passwordText", "");
			ftpGroup.passGroup.passwordText.text = "";
		}

		//restore
		var newItem = {id:newPresetName}; 
		AOM.AmgCreateGallerySection.addItemInfoFromFTPGroup(newItem, group.ftpGroup);
		var index = (duplicateIndex >= 0 ? duplicateIndex : AOM.AMG.ftpPresetUserInput().size());
		AOM.AMG.ftpPresetUserInput().add(newItem, index);

		//add to dropDownlist if necessary
		AOM.AmgCreateGallerySection.hasProgramInteract = true;
		var ftpDropDownList = ftpGroup.tGroup.ftpTemplate;
		if (duplicateIndex >= 0) {
			var item = ftpDropDownList.items[AOM.AmgCreateGallerySection.getListIndexByText(ftpDropDownList, newPresetName)];
			item.text = newPresetName;
			ftpDropDownList.selection = item;
		} else {
			var newItem = ftpDropDownList.add("item", newPresetName);
			ftpDropDownList.selection = newItem;
		}
		AOM.AmgCreateGallerySection.hasProgramInteract = false;
	}

	group.ftpGroup.tGroup.ftpTemplate.document = foldableSet.document;
	group.ftpGroup.tGroup.ftpTemplate.onChange= function() {
		var currentUserInput = AOM.AMG.userInput(this.document);
		if (this.selection != undefined) {
			var selectedPresetName = this.selection.text;
			currentUserInput.set(this.name, selectedPresetName);

			if (!AOM.AmgCreateGallerySection.hasProgramInteract) {
				if (this.selection.index == 0) {
					return;
				}
				var selectedItem= AOM.AMG.ftpPresetUserInput().getById(selectedPresetName);
				if (selectedItem == undefined) {
					AOM.alert(AOM.localize("$$$/AMG/javascript/ftp/noloaditem=No item selected, please select it first."));
					return;
				}

				var ftpGroup = group.ftpGroup;
				ftpGroup.ftpServerText.text = selectedItem.cg_ftpServerText;
				ftpGroup.nameGroup.userNameText.text = AOM.AmgCreateGallerySection.decryptUsername(selectedItem.cg_userNameText);
				ftpGroup.passGroup.passwordText.text = selectedItem.cg_passwordText;
				if ((typeof selectedItem.cg_ftpHasSavePass) == "string") {
					ftpGroup.cpassGroup.ftpHasSavePass.checked = 
						(selectedItem.cg_ftpHasSavePass == "true" || selectedItem.cg_ftpHasSavePass == "1");
				} else {
					ftpGroup.cpassGroup.ftpHasSavePass.checked = selectedItem.cg_ftpHasSavePass;
				}
				ftpGroup.cpassGroup.ftpHasSavePass.notify("onDraw");
				ftpGroup.foldGroup.uploadFolderText.text = selectedItem.cg_uploadFolderText;

				//persist
				AOM.AmgCreateGallerySection.persistFTPGroupValues(ftpGroup, currentUserInput);
			}
		}
	}

	group.ftpGroup.tGroup.ftpDeleteBtn.document = foldableSet.document;
	group.ftpGroup.tGroup.ftpDeleteBtn.onClick = function() {
		var ftpDropDownList = group.ftpGroup.tGroup.ftpTemplate;

		if (ftpDropDownList.selection == undefined || ftpDropDownList.selection.index == 0) {
			AOM.alert(AOM.localize("$$$/AMG/javascript/ftp/nodeleteitem=No item selected, please select it first."));
			return;
		}
		
		var selectedPresetName = ftpDropDownList.selection.text;
		var selectedItem= AOM.AMG.ftpPresetUserInput().getById(selectedPresetName);
		if (selectedItem == undefined) {
			AOM.alert(AOM.localize("$$$/AMG/javascript/ftp/nodeleteitem=No item selected, please select it first."));
			return;
		}

		if(!AOM.confirm(AOM.localize(
			"$$$/AMG/javascript/ftp/reallydelete=Delete current  FTP preset?"))) {
			return;
		}

		//move from dropdownlist
		AOM.AmgCreateGallerySection.hasProgramInteract = true;
		ftpDropDownList.remove(ftpDropDownList.selection.index);
		ftpDropDownList.selection = 0;
		AOM.AmgCreateGallerySection.hasProgramInteract = false;

		//delete from memory.
		AOM.AMG.ftpPresetUserInput().remove(selectedItem);
		app.document = this.document;
	}
}

AOM.AmgFTPPresetUserInput = function() {
	this.ftpPresetItems = new Array();
	this.restore();
}
AOM.AmgFTPPresetUserInput.prototype.getItems = function() {
	return this.ftpPresetItems;
}
AOM.AmgFTPPresetUserInput.prototype.setItems = function(newPresetItems) {
	this.ftpPresetItems = newPresetItems;
}
AOM.AmgFTPPresetUserInput.prototype.size = function() {
	return this.ftpPresetItems.length;
}
AOM.AmgFTPPresetUserInput.prototype.getById = function(presetName) {
	var keyword = presetName.toLowerCase();
	for (var i = 0; i < this.ftpPresetItems.length; i++) {
		var item = this.ftpPresetItems[i];
		if (item.id.toLowerCase() == keyword) {
			return item;
		}
	}
	return undefined;
}
AOM.AmgFTPPresetUserInput.prototype.add = function(item, index) {
	if (index == undefined) {
		index = this.size();
	} 
	this.ftpPresetItems[index] = item;
}
AOM.AmgFTPPresetUserInput.prototype.remove = function(what) {
	var index= -1;
	if (what instanceof Object) {
		index = this.indexOf(what.id);
	} else {
		index = what;
	}
	this.ftpPresetItems.splice(index, 1);
}
AOM.AmgFTPPresetUserInput.prototype.indexOf = function(newPresetName) {
	var findIndex = -1;
	var keyword = newPresetName.toLowerCase();
	for (var i = 0; i < this.ftpPresetItems.length; i++) {
		var item = this.ftpPresetItems[i];
		if (item.id.toLowerCase() == keyword) {
			findIndex = i;
			break;
		}
	}
	return findIndex;
}
AOM.AmgFTPPresetUserInput.prototype.restore = function() {
	var file = new File(AOM.AMG.Paths.persistedFTPPresetUserData);
	if (!file.open("r") || file.length <= AOM.jsonHeaderLength) return;
	
	var json = file.read();
	file.close();

	try {
		var persistedPresets = eval(json);
		if (persistedPresets instanceof Array) {
			for (var i = 0; i < persistedPresets.length; ++i) {
				var item = persistedPresets[i];
				for (var key in item) {
					var value = item[key];
					if (typeof value == "string") {
						item[key] = File.decode(value);
					}
				}
				this.add(item);
			}
		}
	} catch(e) {
		return;
	}
}

AOM.AmgFTPPresetUserInput.prototype.toString = function() {
	var stringBuffer = "[\n";
	var ftpPresetItems = this.ftpPresetItems;
	for (var i = 0; i < ftpPresetItems.length; ++i) {
		var item = ftpPresetItems[i];
		stringBuffer += "{";
		for (var key in item) {
			var value = item[key];
			switch(typeof value) {
				case "string":
					stringBuffer += (key + ":\"" + File.encode(value) + "\", ");
					break;
				case "boolean":
				case "number":
					stringBuffer += (key + ":" + value + ", ");
					break;
				case "object":
				case "function":
				default:
			}
		}
		stringBuffer += "}";
		if (i < ftpPresetItems.length - 1) {
			stringBuffer += ",\n";
		}
	}
	stringBuffer += "\n]";
	return stringBuffer;
}

AOM.AmgFTPPresetUserInput.prototype.persist = function() {
	var file = new File(AOM.AMG.Paths.persistedFTPPresetUserData);
	file.lineFeed = "unix";
	if (!file.open("w"))
		return AOM.AMG.Log.writeError("DesignWindow.UserInput.persist - could not open file ("+file.fsName+")");
	AOM.Utils.writePersistFileHeader(file);
	file.writeln(this.toString());
	file.close();
}

// TODO - create these controls dynamically rather than via script
// TODO - change the control label text so they better describe their function
AOM.AmgCreateGallerySection.foldResourceContents = new String(
"group \
 {  \
 	orientation: 'column', \
	alignment: 'left',\
	margins: 5, spacing:6, \
	galleryLabel: StaticText {text: '" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/galleryName=Gallery Name:") + "', alignment: 'left', preferredSize:[-1, 18]}, \
	galleryText: EditText {preferredSize:[" + (AOM.AmgAccordionSection.accordionButtonWidth - 40) + ", 18], properties:{borderless:true}, name:'cg_galleryText', alignment: 'fill'}, \
	spacer1: Group {preferedSize: [0, 0]} \
	saveGroup: Group \
	{ \
		orientation: 'column', \
		alignment: 'fill', spacing:4, \
		saveLocationGroup: Group \
		{ \
			alignment: ['fill', 'center'], margins:0, \
			saveLocationText: StaticText {text: '" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/SaveLocation=Save Location:") + "', alignment: 'left', preferredSize:[-1, 18]},\
			saveBrowseButton:Custom {\
                type:'customBoundedValue', \
                themeType:'iconbutton', \
                text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/Browse=Browse...") + "', \
                alignment: ['right', 'center'],\
                preferredSize:[100, 20]\
            } \
		}, \
		saveFolderText: EditText {preferredSize:[" + (AOM.AmgAccordionSection.accordionButtonWidth - 40) + ", 18], properties:{borderless:true}, name:'cg_saveFolderText', alignment: 'fill'}, \
	}, \
	spacer2: Group {preferedSize: [0, 0]} \
	ftpGroup: Group \
	{ \
		orientation: 'column', \
		alignment: 'fill', spacing:6,\
		ftpLocationText: StaticText {text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/UploadLocation=Upload Location:") + "', alignment: 'left', preferredSize:[-1, 18]},\
		tGroup:Group{\
			alignment:'left', spacing:5,\
			alignChildren:'left', \
			ftpTemplate:DropDownList{preferredSize:[196, 22], name:'cg_ftpTemplate'},\
			ftpSaveBtn:IconButton{\
				text:'',\
				preferredSize:[20, 20],\
				normalImagePath:'" + AOM.Paths.images + "/new_normal.png" + "',\
				rolloverImagePath:'" + AOM.Paths.images + "/new_rollover.png" + "',\
				disableImagePath:'" + AOM.Paths.images + "/new_disable.png" + "',\
				themeType:'swapbutton',\
				helpTip:' " + AOM.localizeEsc("$$$/AMG/javascript/ftp/savePresetName=Save Preset Name") + "', \
			},\
			ftpDeleteBtn: IconButton{\
				text:'', \
				preferredSize:[20, 20],\
				normalImagePath:'" + AOM.Paths.images + "/delete_normal.png" + "',\
				rolloverImagePath:'" + AOM.Paths.images + "/delete_rollover.png" + "',\
				disableImagePath:'" + AOM.Paths.images + "/delete_disable.png" + "',\
				themeType:'swapbutton',\
				helpTip:' " + AOM.localizeEsc("$$$/AMG/javascript/ftp/deletePresetName=Delete Selected Preset Name") + "', \
			},\
		},\
		ftpServerLabel: StaticText { text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/ftpserver=FTP Server:") + "', alignment: 'left', preferredSize:[-1, 18]}, \
		ftpServerText: EditText {preferredSize:[" + (AOM.AmgAccordionSection.accordionButtonWidth - 40) + ", 18], alignment:'fill', properties:{borderless:true}, name:'cg_ftpServerText'}, \
		nameGroup:Group{\
			alignment:'right', alignChildren:'right', spacing:5,\
			userNameLabel: StaticText { text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/username=User Name:") + "', preferredSize:[-1, 18]}, \
			userNameText: EditText {preferredSize:[168, 18], properties:{borderless:true}, name:'cg_userNameText'}, \
		}\
		passGroup:Group{\
			alignment:'right', alignChildren:'right', spacing:5, \
			passwordLabel: StaticText { text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/password=Password:") + "', preferredSize:[-1, 18]}, \
			passwordText: EditText {preferredSize:[168, 18], properties: {noecho: true, borderless:true}, name:'cg_passwordText'}, \
		}\
		cpassGroup:Group{\
			alignment:'right', alignChildren:'right', spacing:5, \
			hasLabel:StaticText{text:''},\
			ftpHasSavePass:Custom{\
				type:'customBoundedValue',\
				themeType:'customcheckbox', \
				title:'" + AOM.localizeEsc("$$$/AMG/javascript/ftp/rememberPassword=Remember Password") + "', \
				preferredSize:[168, 18], \
				name:'cg_ftpHasSavePass',\
			},\
		}\
		foldGroup:Group{\
			alignment:'right', alignChildren:'right', spacing:5, \
			uploadFolderLabel: StaticText { text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/uploadfolder=Folder:") + "', preferredSize:[-1, 18]}, \
			uploadFolderText: EditText {preferredSize:[168, 18], properties:{borderless:true}, name:'cg_uploadFolderText'}, \
		}\
	} ,\
 }"
 // Not delete in order to avoid ZString scanning warning.
 // AOM.localizeEsc("$$$/AMG/javascript/ftp/storePasswordPlainHint=If you checked Remember Password, The password will be stored in plain text."
);

AOM.AmgHeaderResource =
"group { \
	orientation: 'column', \
	alignment:['left', 'top'],\
	margins:0, spacing:0 \
}";

AOM.AmgCreateGallerySection.saveUploadButtonContents =
"group{\
	name:'foldgroup',\
	orientation:'column', alignment:['fill', 'top'], alignChildren:['left', 'top'], spacing:0, margins:0 ,\
	contentgroup:Group{\
	    margins:[60, 10, 10, 10], spacing:15,\
		saveButton: IconButton {\
			themeType:'iconbutton', \
			preferredSize:[120, 20],\
			text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/save=Save") + "', alignment: 'center'}, \
        ftpButton: IconButton {\
			themeType:'iconbutton', \
			preferredSize:[120, 20],\
			text:'" + AOM.localizeEsc("$$$/MediaGallery/JavaScript/uploadViaFTP=Upload") + "', alignment: 'center'},\
	}\
}";

AOM.AmgSaveUploadGroupEventHanldeInit = function(saveUploadButtonGroup) {
	var aFTPButton = saveUploadButtonGroup.contentgroup.ftpButton;
	aFTPButton.document = saveUploadButtonGroup.document;
	aFTPButton.onClick = function ()
	{
		if (!AOM.AMG.checkEditTextValidOnMac()) return;

		var userInput = AOM.AMG.userInput(this.document);
		var data = new AOM.UploadFormData(userInput.get("cg_galleryText"), userInput.get("cg_ftpServerText"),
			userInput.get("cg_userNameText"), userInput.get("cg_passwordText"), userInput.get("cg_uploadFolderText"),
            this.document);
		if (!data.valid) return;

		AOM.AMG.createGallery(data);
	}

	var aSaveButton = saveUploadButtonGroup.contentgroup.saveButton;
	aSaveButton.document = saveUploadButtonGroup.document;
	aSaveButton.onClick = function ()
	{
		if (!AOM.AMG.checkEditTextValidOnMac()) return;

		var userInput = AOM.AMG.userInput(this.document);
		var data = new AOM.SaveToDiskFormData(
            userInput.get("cg_galleryText"), userInput.get("cg_saveFolderText"), this.document);
		if (!data.valid) return;
		AOM.AMG.createGallery(data);
	}
}


AOM.AmgPreviewWindow = function(document)
{
	this.tabbedPalette = AOM.AmgPreviewWindow.create(document);
	this.tabbedPalette.visible = false;
}
AOM.AmgPreviewWindow.create = function(document)
{
	var tabbedPalette = AOM.AmgTabbedPalette.create(document, "AMG Preview", "amgPreview", "web", undefined);
	return tabbedPalette;
}
AOM.AmgPreviewWindow.prototype.display = function (path)
{
	this.tabbedPalette.url = path;
}

AOM.AmgUserInput = function()
{
	this.initialize();
}
AOM.AmgUserInput.prototype.initialize = function()
{
	this.data = {};
	this.restore();
	// error values start with an underscore - make sure a few always exist
	this.data._idTranslationUndefined = "id translation undefined";
	this.data._bindingMapUndefined = "binding map undefined";
}
AOM.AmgUserInput.prototype.get = function (id)
{
	// Return a value from the user input data store.
	// Returns undefined if id is undefind or there is no value for
	// the given id.
	if (id == undefined)
		return undefined;

	var value = this.data[id];
	return value;
}
AOM.AmgUserInput.prototype.set = function (id, value)
{
	if (id == undefined || value == undefined)
	{
		AOM.AMG.Log.writeError("AOM.AMG.userInput().set - one or more input undefined (id: " + id + ", value:" + value + ")");
		return;
	}
	var valid = this.isValid(id, value);

	if (valid)
		this.data[id] = value;
	// TODO - If value is bad, should we clear out the previous value? Or should we leave the old value?
	// TODO - does anyone need to know if this is valid?
	return valid;
}

AOM.AmgUserInput.validationRules = {};
AOM.AmgUserInput.validationRules.cg_galleryText = [{name:"notEmpty", msg:AOM.localize("$$$/MediaGallery/JavaScript/ftp/requireGalleryName=A gallery name is required.")}, {name:"filename", msg:AOM.localize("$$$/MediaGallery/JavaScript/ftp/galleryNameUseFolder=Gallery name is used as the folder name when the gallery is written to disk or transferred via ftp.\nGallery Name is also used as the value of the <title> element in the gallery's index.html file.")}];
//AOM.AmgUserInput.validationRules.cg_saveFolderText	= [{name:"path"}, {name:"notEmptyIf", id:"cg_saveRadioButton", value:"true", msg:AOM.localize("$$$/MediaGallery/JavaScript/ftp/requireGalleryFoloder=The path for the gallery folder is required.")}];
//AOM.AmgUserInput.validationRules.cg_ftpServerText	= [{name:"notEmptyIf", id:"cg_ftpRadioButton", value:"true", msg:AOM.localize("$$$/MediaGallery/JavaScript/ftp/requrieFTPServer=FTP server is required.")}];
//AOM.AmgUserInput.validationRules.cg_userNameText	= [{name:"notEmptyIf", id:"cg_ftpRadioButton", value:"true", msg:AOM.localize("$$$/MediaGallery/JavaScript/ftp/requireUserName=A user name is required.")}];
AOM.AmgUserInput.doNotPersist = {};
AOM.AmgUserInput.doNotPersist.cg_passwordText = true;
AOM.AmgUserInput.doNotPersist._idTranslationUndefined = true;
AOM.AmgUserInput.doNotPersist._bindingMapUndefined = true;

//TODO
//AOM.AmgUserInput.validationRules.contactInfoLink = [{name:"email", msg:"Contact Info Link is not a correct format"}];

AOM.AmgUserInput.doNotPersistIf = {};
AOM.AmgUserInput.doNotPersistIf.cg_passwordText = { ifcond:"false", ref:"cg_ftpHasSavePass"};
/*
// TODO - dynamically modify the thumb and large values for HTML galleries
AOM.AmgUserInput.validationRules.io_thumbHeight		= [{name:"numberRange", minimum:24, maximum:192}];
AOM.AmgUserInput.validationRules.io_thumbWidth		= [{name:"numberRange", minimum:24, maximum:192}];
AOM.AmgUserInput.validationRules.io_smallHeight		= [{name:"numberRange", minimum:200, maximum:680}];
AOM.AmgUserInput.validationRules.io_smallWidth		= [{name:"numberRange", minimum:200, maximum:680}];
AOM.AmgUserInput.validationRules.io_mediumHeight	= [{name:"numberRange", minimum:300, maximum:900}];
AOM.AmgUserInput.validationRules.io_mediumWidth		= [{name:"numberRange", minimum:300, maximum:900}];
AOM.AmgUserInput.validationRules.io_largeHeight		= [{name:"numberRange", minimum:420, maximum:1275}];
AOM.AmgUserInput.validationRules.io_largeWidth		= [{name:"numberRange", minimum:420, maximum:1275}];
*/

AOM.AmgUserInput.prototype.isValid = function (id, value)
{
	var that = this;
	var checkRules = function (id, value, rules)
	{
		var notValid = function (defaultMsg, ruleMsg)
		{
			/* Work-around for #1840160: In ideal situation, the alert should be displayed by
			 *                           a direct invocation to alert(). It is now the following
			 *                           complicated process, that is, to detect the active status
			 *                           of the window and, in the case of inactive, use a scheduled
			 *                           task in order to avoid Bridge crash. */
			if(that.window.active) {
				AOM.alert(defaultMsg + (ruleMsg != undefined ? "\n\n"+ruleMsg : ""));
			} else {
				AOM.AmgUserInput.popupAlert = function() {
					AOM.alert(defaultMsg + (ruleMsg != undefined ? "\n\n"+ruleMsg : ""));
				};
				app.scheduleTask("AOM.AmgUserInput.popupAlert()", 0, false);
			}
			valid = false;
		}

		for (var i = 0; i < rules.length; i++)
		{
			var rule = rules[i]
			switch (rule.name)
			{
			 case "email":
				if (!AOM.AMG.Tests.isEmail(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidEmail=Does not appear to be a valid email address."));// 
				break;
			case "emailOrURL" :
				if (!AOM.AMG.Tests.isEmailOrURL(value)) {
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidEmailOrURL=Does not appear to be a valid email address or url address."));
				}
				break;
			 case "filename":
				if (!AOM.AMG.Tests.isFilename(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidFileName=Not a valid filename."), rule.msg);
				break;
			 case "filenamePath":
				if (!AOM.AMG.Tests.isFilenamePath(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidFileNameOrPath=Not a valid filename/path."));
				break;
			 case "notEmpty":
				if (!AOM.AMG.Tests.isNotEmpty(value)) {
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/fieldNotEmpty=Field cannot be empty."), rule.msg);
					valid = false;
				}
				break;
			 case "notEmptyIf":
				if (that.get(rule.id).toString() == rule.value.toString())
				{
					if (!AOM.AMG.Tests.isNotEmpty(value))
						notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/fieldNotEmpty=Field cannot be empty."), rule.msg);
				}
				break;
			 case "number":
				if (!AOM.AMG.Tests.isNumber(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/notNumber=Not a number."));
				break;
			 case "numberRange":
				if (!AOM.AMG.Tests.isWithinRange(value, rule.minimum, rule.maximum))
					notValid(AOM.localizeWithArgs("$$$/MediaGallery/JavaScript/validation/invalidRange=Must be a number in the range (1) - (2). ", [rule.minimum, rule.maximum]));
				break;
			 case "path":
				if (!AOM.AMG.Tests.isPath(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidPath=Not a valid path."));
				break;
			 default:
				AOM.AMG.Log.writeError("DesignWindow.UserInput.isValid - unhandled rule ("+rule.name+")");
				break;
			}

			//TODO, if current rule check is fail,  it's better return, otherwise it may pop up two or more alerts.
			if (valid == false) {
				return false;
			}
		}
		return valid;
	}

	var valid = true;
	var rules = AOM.AmgUserInput.validationRules[id];
	if (rules != undefined)
		valid = checkRules(id, value, rules);
	if (valid == true)
	{
		rules = AOM.AmgGalleryMaker.validationRules[id];
		if (rules != undefined)
			checkRules(id, value, rules);
	}
	return valid;
}
AOM.AmgUserInput.loadSizes = function(doc)
{
    var amgGalleryMakerData = AOM.AMG.galleryMakerData(doc);
    var currentUserInput = AOM.AMG.userInput(doc);

	// TODO - this is probably not the best way to set up the 
	// user input size value...
	var thumb = amgGalleryMakerData.sizes.values.thumb;
	if (thumb != undefined)
	{
		currentUserInput.set("io_thumbHeight", thumb.height);
		currentUserInput.set("io_thumbWidth", thumb.width);
	}
	var small = amgGalleryMakerData.sizes.values.small;
	if (small != undefined)
	{
		currentUserInput.set("io_smallHeight", small.height);
		currentUserInput.set("io_smallWidth", small.width);
	}
	var medium = amgGalleryMakerData.sizes.values.medium;
	if (medium != undefined)
	{
		currentUserInput.set("io_mediumHeight", medium.height);
		currentUserInput.set("io_mediumWidth", medium.width);
	}
	var large = amgGalleryMakerData.sizes.values.large;
	if (large != undefined)
	{
		currentUserInput.set("io_largeHeight", large.height);
		currentUserInput.set("io_largeWidth", large.width);
	}
}
AOM.AmgUserInput.persist = function(doc)
{
	// Step through the user input data store and write to disk
	var file = new File(AOM.AMG.Paths.persistedUserData);
	file.lineFeed = "unix";
	if (!file.open("w"))
		return AOM.AMG.Log.writeError("DesignWindow.UserInput.persist - could not open file ("+file.fsName+")");
		
	var write = function(id, value)
	{
		// TODO - escape any double quotes in value...
		file.writeln("{id:\""+id+"\",value:\""+File.encode(value)+"\"},");
	}
	
	AOM.Utils.writePersistFileHeader(file);
	file.writeln("AOM.AmgUserInput.persistedData = [");
	var data = AOM.AMG.userInput(doc).data;
	for (var i in data)
	{
	    if (data[i] == undefined)
	        continue;
		if (AOM.AmgUserInput.doNotPersist[i] == undefined) {
			write(i, data[i]);
		} else {
			var condition = AOM.AmgUserInput.doNotPersistIf[i];
			if (condition != undefined) {
				//if condition has value, get condition value, compare condtion value is equal to real value, if true do not persist, else persist.
				var refValue = data[condition.ref];
				if (data[condition.ref] == condition.ifcond) {
					//AOM.alert('do not persist');
				} else {
					//AOM.alert('persist');
					write(i, data[i]);
				}
			}
			//if (condition != undefined) {
				//var refValue = data[condition.ref];
				//AOM.alert('refvalue=' + refValue);
			//}
		}
	}
	file.writeln("];\n");
	file.close();
	return true;
}
AOM.AMG.Paths.persistUserStylePath = Folder.userData + "/Adobe/Bridge " + AOM.CS_VERSION + "/Adobe Output Module/UserTemplate/MediaGallery/";
AOM.AmgUserInput.persistUserStyle = function(templateName, styleName, doc)
{
	// Step through the user input data store and write to disk
	var folderPath = AOM.AMG.Paths.persistUserStylePath + templateName + "/";
	
	var templateFolder = Folder(folderPath);
	if (!templateFolder.exists) {
		templateFolder.create();
	}
	var filePath = folderPath + styleName + ".json";
	
	var file = new File(filePath);
	
	if (!file.open("w"))
		return AOM.AMG.Log.writeError("DesignWindow.UserInput.persist - could not open file ("+file.fsName+")");
		
	var write = function(id, value)
	{
		file.writeln("{id:\""+id+"\",value:\""+File.encode(value)+"\"},");
	}
	
	AOM.Utils.writePersistFileHeader(file);
	file.writeln("AOM.AmgUserInput.userSavedStyle = [");
	var data = AOM.AMG.userInput(doc).data;
	for (var i in data)
	{
		if (i.indexOf("isOpen") == 0 || i.indexOf("cg_") == 0)
			continue;
		if(i == "mgselectedSection")
			continue;
	    if (data[i] == undefined)
	        continue;
		if (AOM.AmgUserInput.doNotPersist[i] == undefined) {
			write(i, data[i]);
		} else {
			var condition = AOM.AmgUserInput.doNotPersistIf[i];
			if (condition != undefined) {
				//if condition has value, get condition value, compare condtion value is equal to real value, if true do not persist, else persist.
				var refValue = data[condition.ref];
				if (data[condition.ref] != condition.ifcond)
					write(i, data[i]);
			}
		}
	}
	file.writeln("];\n");
	file.close();
	return true;
}


AOM.AmgUserInput.prototype.restore = function()
{
	var file = new File(AOM.AMG.Paths.persistedUserData);
	if (!file.open("r") || file.length <= AOM.jsonHeaderLength)	return;
		
	var json = file.read();
	file.close();

	try {
		eval(json);	
		var data = AOM.AmgUserInput.persistedData;
		for (var i = 0; i < data.length; ++i) {
			var d = data[i];
			this.set(d.id, File.decode(d.value));
		}
	} catch(e) {
		return;
	}
}
AOM.AmgUserInput.deletePersistedData = function()
{
	var file = new File(AOM.AMG.Paths.persistedUserData);
	if (file.exists)
		return file.remove()
	return true;
}
AOM.AmgUserInput.dump = function ()
{
	AOM.AMG.Log.writeLine("AOM.AmgUserInput.dump...");
	try
	{
		var dump = function (data)
		{
			for (var i in data)
				AOM.AMG.Log.writeLine(i + ": " + data[i]);
		}
		dump(AOM.AMG.userInput().data);
	}
	catch (e)
	{
		AOM.alert(e);
		AOM.AMG.Log.writeError("AOM.AmgUserInput.dump caught - " + e);
	}
	AOM.AMG.Log.writeLine("...AOM.AmgUserInput.dump");
}
AOM.AmgUserInput.htmlEncoding = function(value) {
	if (value == undefined || value.length == 0) return value;
	
	value = value.replace(/&/g, "&amp;"); 
	value = value.replace(/</g, "&lt;");
	value = value.replace(/>/g, "&gt;");
	value = value.replace(/\'/g, "&#39;");
	value = value.replace(/\"/g, "&quot;");
	return value;
}

AOM.AmgValidator = function() {};
AOM.AmgValidator.reset = function ()
{
	this.problemsFound = false;
	this.problemsDescription = "";
	this.errorStrings = new Array();
}
AOM.AmgValidator.testIdValue = function (id, value)
{
	var valid = true;
	var rules = AOM.AmgUserInput.validationRules[id];
	if (rules != undefined)
		valid = this.testValue(value, rules);

	rules = AOM.AmgGalleryMaker.validationRules[id];
	if (rules != undefined)
		valid = this.testValue(value, rules);

	return valid;
}
AOM.AmgValidator.testIdValueList = function (idValueList)
{
	for (var i = 0; i < idValueList.length; i++)
	{
		ivi = idValueList[i]; // id value item
		this.testIdValue(ivi.id, ivi.value);
	}
}
AOM.AmgValidator.testValueList = function (valueList)
{
	for (var i = 0; i < valueList.length; i++)
	{
		vli = valueList[i];
		this.testValue(vli.value, vli.rules);
	}
}
AOM.AmgValidator.errors = function ()
{
	var s = "";
	for (var i = 0; i < this.errorStrings.length; i++)
	{
		e = errorStrings.shift();
		s += e.error + " (" + e.detail + ")\n\n";
	}
	return s;
}
AOM.AmgValidator.testValue = function (value, rules)
{
	var valid = true;
	var notValid = function (defaultMsg, ruleMsg)
	{
		this.errorStrings.push({error:defaultMsg, detail:ruleMsg});
		valid = false;
	}
	for (var i = 0; i < rules.length; i++)
	{
		var rule = rules[i]
		switch (rule.name)
		{
		 case "email":
			if (!AOM.AMG.Tests.isEmail(value))
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidEmail=Does not appear to be a valid email address."));// 
			break;
		case "emailOrURL" :
			if (!AOM.AMG.Tests.isEmailOrURL(value)) {
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidEmailOrURL=Does not appear to be a valid email address or url address."));
			}
			break;
		 case "filename":
			if (!AOM.AMG.Tests.isFilename(value))
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidFileName=Not a valid filename."), rule.msg);
			break;
		 case "filenamePath":
			if (!AOM.AMG.Tests.isFilenamePath(value))
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidFileNameOrPath=Not a valid filename/path."));
			break;
		 case "notEmpty":
			if (!AOM.AMG.Tests.isNotEmpty(value))
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/fieldNotEmpty=Field cannot be empty."), rule.msg);
			break;
		 case "notEmptyIf":
			if (AOM.AMG.userInput().get(rule.id).toString() == rule.value.toString())
			{
				if (!AOM.AMG.Tests.isNotEmpty(value))
					notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/fieldNotEmpty=Field cannot be empty."), rule.msg);
			}
			break;
		 case "number":
			if (!AOM.AMG.Tests.isNumber(value))
				notValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/notNumber=Not a number."));
			break;
		 case "numberRange":
			if (!AOM.AMG.Tests.isWithinRange(value, rule.minimum, rule.maximum))
				notValid(AOM.localizeWithArgs("$$$/MediaGallery/JavaScript/validation/invalidRange=Must be a number in the range (1) - (2). ", [rule.minimum, rule.maximum]));
			break;
		 case "path":
			if (!AOM.AMG.Tests.isPath(value))
				otValid(AOM.AMG.localize("$$$/MediaGallery/JavaScript/validation/invalidPath=Not a valid path."));
			break;
		 default:
			AOM.AMG.Log.writeError("DesignWindow.UserInput.isValid - unhandled rule ("+rule.name+")");
			break;
		}

		//TODO, if current rule check is fail,  it's better return, otherwise it may pop up two or more alerts.
		if (valid == false) {
			return false;
		}
	}
	return valid;
}


AOM.AMG.ExternalObject= {};
AOM.AMG.ExternalObject.lastPath = undefined;
AOM.AMG.ExternalObject.create = function (file)
{
	AOM.AMG.ExternalObject.lastPath = AOM.AMG.Paths.resources + "plugins/" + file;
	var f = new File(AOM.AMG.ExternalObject.lastPath);
	if (f.exists)
	{
		var externalObject = new ExternalObject("lib:" + f.fsName);
		//if (typeof externalObject == "object")
		if (externalObject instanceof ExternalObject)
			return externalObject;
	}
	return undefined
}

AOM.AMG.WebAccess = {}
AOM.AMG.WebAccess.externalObject = undefined;
AOM.AMG.WebAccess.ftp = function ()
{
	// returns an ftp object
	if (AOM.AMG.WebAccess.externalObject == undefined)
	{
		if (AOM.AMG.WebAccess.open() == undefined)
			return undefined;
	}
	return new AOM.Ftp();
}
AOM.AMG.WebAccess.open = function ()
{
	AOM.AMG.WebAccess.externalObject = AOM.AMG.ExternalObject.create(File.fs == "Macintosh" ? "FtpConnection.bundle" : "FtpConnection.dll");
	if (typeof AOM.AMG.WebAccess.externalObject == "object")
		return true;
	AOM.AMG.Log.writeError("WebAccess.initialize - could not get external object (" + AOM.AMG.ExternalObject.lastPath + ")");
	return false;
}
AOM.AMG.WebAccess.unload = function ()
{
	if (AOM.AMG.WebAccess.externalObject != undefined)
	{
		AOM.AMG.WebAccess.externalObject.unload();
		AOM.AMG.WebAccess.externalObject = undefined;
		AOM.AMG.Log.writeLine("WebAccess.unload()...");
	}
}

AOM.AMG.Xslt = {};
AOM.AMG.Xslt.externalObject = undefined;
AOM.AMG.Xslt.transform = function (xml, xslt, out)
{
	if (AOM.AMG.Xslt.externalObject == undefined)
	{
		if (AOM.AMG.Xslt.initialize() == false)
		{
			AOM.alert("Could not open XSLT");
			return false;
		}
	}
	var filesExist = function (files)
	{
		var ok = true;
		for (var i = 0; i < files.length; i++)
		{
			var f = files[i];
			if (!f.exists)
			{
				AOM.AMG.Log.writeError("Xslt.transform - can't find '" + f.fsName + "'");
				ok = false;
			}
		}
		return ok;
	}
	if (filesExist([xml, xslt]))
	{
		// xslt return 0 if all's okay...
		return AOM.AMG.Xslt.externalObject.xslt(xml.fsName, xslt.fsName, out.fsName) == 0 ? true : false;
	}
	return false;
}
AOM.AMG.Xslt.initialize = function ()
{
	if (AOM.AMG.Xslt.externalObject != undefined)
	{
		AOM.AMG.Log.writeError("Xslt.initialize - externalObject not undefined");
		return true; // DWR - can we test that it is actually the an xslt?
	}
	AOM.AMG.Xslt.externalObject = AOM.AMG.ExternalObject.create(File.fs == "Macintosh" ? "XSLT.bundle" : "XSLT.dll");
	if (typeof AOM.AMG.Xslt.externalObject == "object")
		return true;
	AOM.AMG.Log.writeError("Xslt.initialize - could not get external object (" + AOM.AMG.ExternalObject.lastPath + ")");
	return false;
}
AOM.AMG.Xslt.unload = function ()
{
	if (AOM.AMG.Xslt.externalObject != undefined)
	{
		AOM.AMG.Xslt.externalObject.unload();
		AOM.AMG.Xslt.externalObject = undefined;
		AOM.AMG.Log.writeLine("Xslt.unload()...");
	}
}

AOM.AMG.Colorpicker = {};
AOM.AMG.Colorpicker.pick = function(color)
{
	return $.colorPicker(color);
}
AOM.AMG.Colorpicker.rgb = function (color)
{
	var blue  = (color & 0xFF)/255.0; color = color >>> 8;
	var green = (color & 0xFF)/255.0; color = color >>> 8;
	var red   = (color & 0xFF)/255.0;
	return [red, green, blue];
}
AOM.AMG.Colorpicker.get = function (id, doc)
{
	var color = 0x123456;
	var x = AOM.AMG.userInput(doc).get(id);
	if (x == undefined)
	{
		if (!AOM.AMG.disableColorpickerGetErrorMessages)
		{
			msg = "Colorpicker.get - id returned undefined ("+id+")";
			if (AOM.AMG.trackDocId)
				msg += ", doc.id = " + doc.id;
			AOM.AMG.Log.writeError(msg);
		}
	}
	else
		color = parseInt(x, 16);
	return color
}
AOM.AMG.Colorpicker.set = function (id, color, doc)
{
	var s = color.toString(16);
	while (s.length < 6)
	{
		s = "0" + s;
	}
	AOM.AMG.userInput(doc).set(id, s);
}

// TODO - decide if test shoud throw an exception or just return false
AOM.AMG.Tests = {};
AOM.AMG.Tests.isGroup = function (o)
{
	// For our purposes a group or a panel is considered a group...
	if (o instanceof Group || o instanceof Panel)
		return true;
	throw "AOM.AMG.Tests.isGroup - o was not a Group or Panel";
}
AOM.AMG.Tests.isString = function (s)
{
	if (s instanceof String == false)
		throw "AOM.AMG.Tests.isString - s was not a String";
	return true;
}
AOM.AMG.Tests.isDocument = function (d)
{
	if (d instanceof Document == false)
		throw "AOM.AMG.Test.isDocument - d was not a Docuement";
	return true;
}

/*
AOM.AMG.Tests.isEmail = function (s)
{
	var str = new String(s);
	// an empty string is ok for our purposes...
	if (str.amgIsEmpty())
		return true;
	// allow almost anything in the local portion of the address and restrict to alphanumeric, dash and period in the domain portion
	var r1 = /^[a-zA-Z0-9!#\$%&'\*+-=?^_`{\|}\.]+@([a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$/;
	return str.match(r1);
}
*/

AOM.AMG.Tests.isEmail = function(data) {
	if(data == "")
		return true;
    return /^[a-zA-Z0-9_\-.]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]+$/.test(data);
}


AOM.AMG.Tests.isURL = function(data) {
	/*
    var e=/((http|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)(([\w\-\.]+\.[^#?\s]+)(#[\w\-]+)?)?/;

    if (data.match(e)) {
        return  true;
	} else {
        return  false;
    }
	*/
	//loose validation
	var regTextUrl = /^(file|http|https|ftp|mms|telnet|news|wais|mailto):\/\/(.+)$/;
	return regTextUrl.test(data);
}

AOM.AMG.Tests.isSupportedURL = function(data) {
	/*
    var e=/((http|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)(([\w\-\.]+\.[^#?\s]+)(#[\w\-]+)?)?/;

    if (data.match(e)) {
        return  true;
	} else {
        return  false;
    }
	*/
	//loose validation
	var regTextUrl = /^(http|mailto):\/\/(.+)$/;
	return regTextUrl.test(data);
}

AOM.AMG.Tests.isEmailOrURL = function(data) {
	if (AOM.AMG.Tests.isEmail(data)) {
		return true;
	} 

	if (AOM.AMG.Tests.isSupportedURL(data)) {
		return true;
	}

	if (AOM.AMG.Tests.isURL(data)) {
		return false;
	}

	return true;
}


AOM.AMG.Tests.isFilename = function (s)
{
	var str = new String(s);
	return str.amgIsValidFile();
}
AOM.AMG.Tests.isNotEmpty = function (s)
{
	// this returns true for s == undefined. is that ok?
	var str = new String(s);
	return (str.amgIsEmpty() ? false : true);
}
AOM.AMG.Tests.isNumber = function (v)
{
	return (v == v * 1.0)
}
AOM.AMG.Tests.isWithinRange = function (v, min, max)
{
	if (!AOM.AMG.Tests.isNumber(v))
		return false;
	return (v >= min && v <= max);
}
AOM.AMG.Tests.isPath = function (s)
{
	var str = new String(s);
	// Bridge can't write to root of Mac so watch for that too
	if (File.fs == "Macintosh" && str.amgTrim() == "/")
	{
		AOM.alert("Gallery cannot be saved at the root");
		return false
	}
	return str.amgIsValidPath();
}


AOM.AMG.Log = {}
AOM.AMG.Log.logFile = undefined;
AOM.AMG.Log.initializeLogFile = function ()
{
	if (AOM.AMG.placeLogFileInUserHome)
		this.logFile = new File("~/amg.log");
	else
		this.logFile = new File(AOM.AMG.Paths.log + "amg.log"); 
	this.logFile.lineFeed = "unix"; // use unix line endings so it works with utilities like tail
	if (this.logFile.open("w", "TEXT", "????"))
	{
		this.logFile.close();
		return;
	}
	AOM.alert("AOM.AMG.Log.openLogFile - could not open logFile (" + this.logFile.fsName + ")");
	this.logFile = undefined;
}
AOM.AMG.Log.writeLine = function (line)
{
	// the log is not written immediately on Windows, so we
	// open and close each time to flush the buffer...
	if (this.logFile == undefined)
		return;
	if (!this.logFile.open("e", "TEXT", "????"))
		return;
	this.logFile.seek(0, 2); // seek to the end of the file
	this.logFile.writeln(line);
	this.logFile.close();
}
AOM.AMG.Log.errorsDetected = false;
AOM.AMG.Log.writeError = function (error)
{
	this.writeLine("Error:  "  + error);
	AOM.AMG.Log.errorsDetected = true;
	return undefined;
}
AOM.AMG.Log.writeNote = function (note)
{
	this.writeLine("Note:   "  + note);
}
AOM.AMG.Log.dumpObject = function (object, text)
{
	if (object == undefined)
	{
		AOM.AMG.Log.writeError("dumpObject - object was undefined");
		return;
	}

	AOM.AMG.Log.writeLine("dumpObject...");

	if (text != undefined)
		AOM.AMG.Log.writeLine(text);

	var properties = object.reflect.properties;
	for (var i = 0; i < properties.length; i++)
	{
		if (properties[i] != undefined)
			AOM.AMG.Log.writeLine(object.reflect.name + "." + properties[i].name + " == " + object[properties[i].name]);
	}
	var methods = object.reflect.methods;
	for (i = 0; i < methods.length; i++)
	{
		if (methods[i] != undefined)
			AOM.AMG.Log.writeLine(object.reflect.name + "." + methods[i].name + "()");
	}

	AOM.AMG.Log.writeLine("...dumpObject");
}

AOM.AmgTimer = function()
{
	this.startTime = new Date();
}
AOM.AmgTimer.prototype.elapsed = function ()
{
	return (new Date()).getTime() - this.startTime;
}
