////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package com.flexcapacitor.controller {
	import com.flexcapacitor.components.DocumentContainer;
	import com.flexcapacitor.components.IDocumentContainer;
	import com.flexcapacitor.effects.core.CallMethod;
	import com.flexcapacitor.events.HistoryEvent;
	import com.flexcapacitor.events.HistoryEventItem;
	import com.flexcapacitor.events.RadiateEvent;
	import com.flexcapacitor.logging.RadiateLogTarget;
	import com.flexcapacitor.model.AttachmentData;
	import com.flexcapacitor.model.Device;
	import com.flexcapacitor.model.Document;
	import com.flexcapacitor.model.DocumentData;
	import com.flexcapacitor.model.EventMetaData;
	import com.flexcapacitor.model.IDocument;
	import com.flexcapacitor.model.IDocumentData;
	import com.flexcapacitor.model.IDocumentMetaData;
	import com.flexcapacitor.model.IProject;
	import com.flexcapacitor.model.IProjectData;
	import com.flexcapacitor.model.ISavable;
	import com.flexcapacitor.model.ImageData;
	import com.flexcapacitor.model.InspectableClass;
	import com.flexcapacitor.model.InspectorData;
	import com.flexcapacitor.model.MetaData;
	import com.flexcapacitor.model.Project;
	import com.flexcapacitor.model.SaveResultsEvent;
	import com.flexcapacitor.model.SavedData;
	import com.flexcapacitor.model.Settings;
	import com.flexcapacitor.model.StyleMetaData;
	import com.flexcapacitor.services.IServiceEvent;
	import com.flexcapacitor.services.WPAttachmentService;
	import com.flexcapacitor.services.WPService;
	import com.flexcapacitor.services.WPServiceEvent;
	import com.flexcapacitor.tools.ITool;
	import com.flexcapacitor.utils.ClassUtils;
	import com.flexcapacitor.utils.DisplayObjectUtils;
	import com.flexcapacitor.utils.SharedObjectUtils;
	import com.flexcapacitor.utils.TypeUtils;
	import com.flexcapacitor.utils.XMLUtils;
	import com.flexcapacitor.utils.supportClasses.ComponentDefinition;
	import com.flexcapacitor.utils.supportClasses.ComponentDescription;
	import com.flexcapacitor.views.IInspector;
	import com.google.code.flexiframe.IFrame;
	
	import flash.desktop.Clipboard;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.IBitmapDrawable;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.external.ExternalInterface;
	import flash.geom.Point;
	import flash.globalization.DateTimeStyle;
	import flash.net.FileReference;
	import flash.net.SharedObject;
	import flash.system.ApplicationDomain;
	import flash.ui.Mouse;
	import flash.ui.MouseCursorData;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	
	import mx.collections.ArrayCollection;
	import mx.containers.Grid;
	import mx.containers.GridItem;
	import mx.containers.GridRow;
	import mx.containers.TabNavigator;
	import mx.controls.LinkButton;
	import mx.core.ClassFactory;
	import mx.core.DeferredInstanceFromFunction;
	import mx.core.IUIComponent;
	import mx.core.IVisualElement;
	import mx.core.IVisualElementContainer;
	import mx.core.UIComponent;
	import mx.core.mx_internal;
	import mx.effects.effectClasses.PropertyChanges;
	import mx.graphics.ImageSnapshot;
	import mx.graphics.SolidColor;
	import mx.logging.AbstractTarget;
	import mx.logging.ILogger;
	import mx.logging.Log;
	import mx.logging.LogEventLevel;
	import mx.managers.ILayoutManager;
	import mx.managers.LayoutManager;
	import mx.printing.FlexPrintJob;
	import mx.printing.FlexPrintJobScaleType;
	import mx.states.AddItems;
	import mx.styles.IStyleClient;
	import mx.utils.ArrayUtil;
	import mx.utils.ObjectUtil;
	
	import spark.components.Application;
	import spark.components.BorderContainer;
	import spark.components.Button;
	import spark.components.ComboBox;
	import spark.components.Grid;
	import spark.components.Image;
	import spark.components.Label;
	import spark.components.NavigatorContent;
	import spark.components.Scroller;
	import spark.components.SkinnableContainer;
	import spark.components.supportClasses.GroupBase;
	import spark.components.supportClasses.SkinnableTextBase;
	import spark.components.supportClasses.TextBase;
	import spark.core.ContentCache;
	import spark.core.IViewport;
	import spark.effects.SetAction;
	import spark.formatters.DateTimeFormatter;
	import spark.layouts.BasicLayout;
	import spark.primitives.BitmapImage;
	import spark.primitives.Rect;
	import spark.skins.spark.DefaultGridItemRenderer;
	
	import org.as3commons.lang.ArrayUtils;
	import org.as3commons.lang.DictionaryUtils;
	import org.as3commons.lang.ObjectUtils;
	
	use namespace mx_internal;
	
	/**
	 * Dispatched when register results are received
	 * */
	[Event(name="registerResults", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a print job is cancelled
	 * */
	[Event(name="printCancelled", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when an item is added to the target
	 * */
	[Event(name="addItem", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when an item is removed from the target
	 * */
	[Event(name="removeItem", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when an item is removed from the target
	 * */
	[Event(name="removeTarget", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the target is changed
	 * */
	[Event(name="targetChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the document is changed
	 * */
	[Event(name="documentChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a document is opening
	 * */
	[Event(name="documentOpening", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a document is opened
	 * */
	[Event(name="documentOpen", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a document is renamed
	 * */
	[Event(name="documentRename", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the project is changed
	 * */
	[Event(name="projectChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the project is deleted
	 * */
	[Event(name="projectDeletedResults", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the project is created
	 * */
	[Event(name="projectCreated", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a property on the target is changed. 
	 * Using propertyChanged instead of propertyChange because of error with bindable
	 * tag using propertyChange:
	 * TypeError: Error #1034: Type Coercion failed: cannot convert mx.events::PropertyChangeEvent@11d2187b1 to com.flexcapacitor.events.RadiateEvent.
	 * */
	[Event(name="propertyChanged", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a property is selected on the target
	 * */
	[Event(name="propertySelected", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a property edit is requested
	 * */
	[Event(name="propertyEdit", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the tool changes
	 * */
	[Event(name="toolChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the scale changes
	 * */
	[Event(name="scaleChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the document size or scale changes
	 * */
	[Event(name="documentSizeChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Not used yet. 
	 * */
	[Event(name="initialized", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Used when the tools list has been updated. 
	 * */
	[Event(name="toolsUpdated", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Used when the components list is updated. 
	 * */
	[Event(name="componentsUpdated", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Used when the document canvas is updated. 
	 * */
	[Event(name="canvasChange", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Event to request a preview if available. Used for HTML preview. 
	 * */
	[Event(name="requestPreview", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when the generated code is updated. 
	 * */
	[Event(name="codeUpdated", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when a color is selected. 
	 * */
	[Event(name="colorSelected", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Dispatched when an object is selected 
	 * */
	[Event(name="objectSelected", type="com.flexcapacitor.radiate.events.RadiateEvent")]
	
	/**
	 * Main class and API that handles the interactions between the view and the models. 
	 * 
	 * Dispatches events and exposes methods to manipulate the documents.
	 *  
	 * It contains a list of components, tools, devices, inspectors (panels), assets and 
	 * in the future we should add skins, effects and so on. 
	 * These items are created from an XML file at startup so we can configure what is available
	 * to our user or project. We do this so we can also load in a remote SWF to add 
	 * additional components, sounds, images, skins, inspectors, fonts, etc
	 * 
	 * Currently we are saving and loading to a remote location or to a local shared object. 
	 * To save to a local file system we will need to modify these functions. 
	 * 
	 * This class supports an Undo / Redo history. The architecture is loosely based on 
	 * the structure found in the Effects classes. We may want to be a proxy to the documents
	 * and call undo and redo on them since we would like to support more than one 
	 * type of document. 
	 * 
	 * This class can be broken up into multiple classes since it is also handling 
	 * saving and loading and services. 
	 * 
	 * To set a property or style call setProperty or setStyle. 
	 * To add a component call addElement. 
	 * To log a message to the console call Radiate.log.info() or error().
	 * 
	 * To undo call undo
	 * To redo call redo
	 * 
	 * To get the history index access history index
	 * To check if history exists call the has history
	 * To check if undo can be performed access has undo
	 * To check if redo can be performed access has redo 
	 * 
	 * Editing through cut, copy and paste is only partially implemented. 
	 * */
	public class Radiate extends EventDispatcher {
		
		public static const SAME_OWNER:String = "sameOwner";
		public static const SAME_PARENT:String = "sameParent";
		public static const ADDED:String = "added";
		public static const MOVED:String = "moved";
		public static const REMOVED:String = "removed";
		public static const ADD_ERROR:String = "addError";
		public static const REMOVE_ERROR:String = "removeError";
		public static const RADIATE_LOG:String = "radiate";
		public static const LOGGED_IN:String = "loggedIn";
		public static const LOGGED_OUT:String = "loggedOut";
		
		public function Radiate(s:SINGLEDOUBLE) {
			super(target as IEventDispatcher);
			
			// Create a target
			setLoggingTarget(defaultLogTarget);
			
			
			// initialize - maybe call on startup() instead
			initialize();
		}
		
		//----------------------------------
		//  instance
		//----------------------------------
		private static var _instance:Radiate;
		
		/**
		 * Attempt to support a console part 2
		 * */
		public static function get log():ILogger {
			
			if (_log) {
				return _log;
			}
			else {
				setLoggingTarget(defaultLogTarget);
				return _log;
			}
		}

		/**
		 * @private
		 */
		public static function set log(value:ILogger):void {
			_log = value;
		}

		/**
		 * Attempt to support a console part 3
		 * */
		public static function get console():Object {
			return _console;
		}

		/**
		 * @private
		 */
		public static function set console(value:Object):void {
			_console = value;
			
			if ("console" in logTarget) {
				logTarget["console"] = value;
			}
		}

		public static function get instance():Radiate
		{
			if (!_instance) {
				_instance = new Radiate(new SINGLEDOUBLE());
			}
			return _instance;
		}
		
		public static function getInstance():Radiate {
			return instance;
		}
		
		/**
		 * Create references for classes we need.
		 * */
		public static var radiateReferences:RadiateReferences;
		
		/**
		 * If true then importing document
		 * */
		public static var importingDocument:Boolean;
		
		/**
		 * Upload attachment
		 * */
		public var uploadAttachmentService:WPAttachmentService;
		
		/**
		 * Service to get list of attachments
		 * */
		public var getAttachmentsService:WPService;
		
		/**
		 * Service to get list of projects
		 * */
		public var getProjectsService:WPService;
		
		/**
		 * Service to delete attachment
		 * */
		public var deleteAttachmentService:WPService;
		
		/**
		 * Service to delete document
		 * */
		public var deleteDocumentService:WPService;
		
		/**
		 * Service to delete project
		 * */
		public var deleteProjectService:WPService;
		
		/**
		 * Service to request reset the password
		 * */
		public var lostPasswordService:WPService;
		
		/**
		 * Service to change the password
		 * */
		public var changePasswordService:WPService;
		
		/**
		 * Service to login
		 * */
		public var loginService:WPService;
		
		/**
		 * Service to logout
		 * */
		public var logoutService:WPService;
		
		/**
		 * Service to register
		 * */
		public var registerService:WPService;
		
		/**
		 * Service to check if user is logged in
		 * */
		public var getLoggedInStatusService:WPService;
		
		/**
		 * Set to true when a document is being saved to the server
		 * */
		[Bindable]
		public var saveDocumentInProgress:Boolean;
		
		/**
		 * Set to true when project is being saved to the server
		 * */
		[Bindable]
		public var saveProjectInProgress:Boolean;
		
		/**
		 * Set to true when checking if user is logged in
		 * */
		[Bindable]
		public var getLoggedInStatusInProgress:Boolean;
		
		/**
		 * Set to true when lost password call is made
		 * */
		[Bindable]
		public var lostPasswordInProgress:Boolean;
		
		/**
		 * Set to true when changing password
		 * */
		[Bindable]
		public var changePasswordInProgress:Boolean;
		
		/**
		 * Set to true when registering
		 * */
		[Bindable]
		public var registerInProgress:Boolean;
		
		/**
		 * Set to true when logging in
		 * */
		[Bindable]
		public var loginInProgress:Boolean;
		
		/**
		 * Set to true when logging out
		 * */
		[Bindable]
		public var logoutInProgress:Boolean;
		
		/**
		 * Set to true when deleting a project
		 * */
		[Bindable]
		public var deleteProjectInProgress:Boolean;
		
		/**
		 * Set to true when deleting a document
		 * */
		[Bindable]
		public var deleteDocumentInProgress:Boolean;
		
		/**
		 * Set to true when deleting an attachment
		 * */
		[Bindable]
		public var deleteAttachmentInProgress:Boolean;
		
		/**
		 * Set to true when getting list of attachments
		 * */
		[Bindable]
		public var getAttachmentsInProgress:Boolean;
		
		/**
		 * Set to true when uploading an attachment
		 * */
		[Bindable]
		public var uploadAttachmentInProgress:Boolean;
		
		/**
		 * Set to true when getting list of projects
		 * */
		[Bindable]
		public var getProjectsInProgress:Boolean;
		
		/**
		 * Is user logged in
		 * */
		[Bindable]
		public var isUserLoggedIn:Boolean;
		
		/**
		 * Default storage location for save and load. 
		 * */
		[Bindable]
		public var defaultStorageLocation:String;
		
		/**
		 * Can user connect to the service
		 * */
		[Bindable]
		public var isUserConnected:Boolean;
		
		/**
		 * Avatar of user
		 * */
		[Bindable]
		public var userAvatar:String = "assets/images/icons/gravatar.png";
		
		/**
		 * Path to default avatar of user (from Gravatar)
		 * Gravatars icons don't work locally so using path. 
		 * Default - http://0.gravatar.com/avatar/ad516503a11cd5ca435acc9bb6523536?s=96
		 * local - assets/images/icons/gravatar.png
		 * */
		[Bindable]
		public var defaultUserAvatarPath:String = "assets/images/icons/gravatar.png";
		
		/**
		 * User info
		 * */
		[Bindable]
		public var user:Object;
		
		/**
		 * User email
		 * */
		[Bindable]
		public var userEmail:String;
		
		/**
		 * User id
		 * */
		[Bindable]
		public var userID:int = -1;
		
		/**
		 * User sites
		 * */
		[Bindable]
		public var userSites:Array = [];
		
		/**
		 * User site path
		 * */
		[Bindable]
		public var userSitePath:String;
		
		/**
		 * User display name
		 * */
		[Bindable]
		public var userDisplayName:String = "guest";
		
		/**
		 * Last save date
		 * */
		[Bindable]
		public var lastSaveDate:String;
		
		/**
		 * Cut data
		 * */
		public var cutData:Object;
		
		/**
		 * Cut data
		 * */
		public var copiedData:Object;
		
		/**
		 * Auto save locations
		 * */
		[Bindable]
		public var autoSaveLocations:String;
		
		private var _enableAutoSave:Boolean;

		[Bindable]
		/**
		 * Auto save enabled
		 * */
		public function get enableAutoSave():Boolean {
			return _enableAutoSave;
		}

		/**
		 * @private
		 */
		public function set enableAutoSave(value:Boolean):void {
			_enableAutoSave = value;
			
			
			if (value) {
				if (!autoSaveEffect) {
					autoSaveEffect =  new CallMethod();
					autoSaveEffect.method = autoSaveHandler;
					autoSaveEffect.repeatCount = 0;
					autoSaveEffect.repeatDelay = autoSaveInterval;
				}
				if (!autoSaveEffect.isPlaying) {
					autoSaveEffect.play();
				}
			}
			else {
				autoSaveEffect.stop();
			}
		}
		
		/**
		 * Interval to check to save project
		 * */
		public var autoSaveInterval:int = 30000;
		
		/**
		 * Effect to auto save
		 * */
		public var autoSaveEffect:CallMethod;
		
		/**
		 * Handle auto saving 
		 * */
		public function autoSaveHandler():void {
			var length:int;
			var iProject:IProject;
			var iDocumentData:IDocumentData;
			var iAttachmentData:AttachmentData;
			var imageData:ImageData;
			var i:int;
			
			// save documents
			/*length = documents.length;
			for (i=0;i<length;i++) {
				iDocumentData = documents[i] as IDocumentData;
				if (iDocumentData.isChanged && !iDocumentData.saveInProgress && iDocumentData.isOpen) {
					iDocumentData.save();
				}
			}*/
			
			// save projects
			length = projects.length;
			for (i=0;i<length;i++) {
				iDocumentData = projects[i] as IDocumentData;
				//if (iDocumentData.isChanged && !iDocumentData.saveInProgress && iDocumentData.isOpen) {
				if (!iDocumentData.saveInProgress && iDocumentData.isOpen) {
					iDocumentData.save();
				}
			}
			
			// save attachments
			length = assets.length;
			for (i=0;i<length;i++) {
				iAttachmentData = assets[i] as ImageData;
				if (iAttachmentData) {
					imageData = iAttachmentData as ImageData;
					
					if (!imageData.saveInProgress && imageData.id==null) {
						//imageData.save();
						uploadAttachment(imageData.byteArray, selectedProject.id, imageData.name, null, imageData.contentType);
					}
				}
			}
		}

		/**
		 * Build number
		 * */
		[Bindable]
		public var buildNumber:String;
		
		/**
		 * Build date
		 * */
		[Bindable]
		public var buildDate:String;
		
		/**
		 * Build time
		 * */
		[Bindable]
		public var buildTime:String;
		
		//----------------------------------
		//
		//  Events Management
		// 
		//----------------------------------
		
		/**
		 * Dispatch attachments received event
		 * */
		public function dispatchGetProjectsListResultsEvent(data:Object):void {
			var projectsListResultEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECTS_LIST_RECEIVED);
			
			if (hasEventListener(RadiateEvent.PROJECTS_LIST_RECEIVED)) {
				projectsListResultEvent.data = data;
				dispatchEvent(projectsListResultEvent);
			}
		}
		
		/**
		 * Dispatch print cancelled event
		 * */
		public function dispatchPrintCancelledEvent(data:Object, printJob:FlexPrintJob):void {
			var printCancelledEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PRINT_CANCELLED);
			
			if (hasEventListener(RadiateEvent.PRINT_CANCELLED)) {
				printCancelledEvent.data = data;
				printCancelledEvent.selectedItem = printJob;
				dispatchEvent(printCancelledEvent);
			}
		}
		
		/**
		 * Dispatch print complete event
		 * */
		public function dispatchPrintCompleteEvent(data:Object, printJob:FlexPrintJob):void {
			var printCompleteEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PRINT_COMPLETE);
			
			if (hasEventListener(RadiateEvent.PRINT_COMPLETE)) {
				printCompleteEvent.data = data;
				printCompleteEvent.selectedItem = printJob;
				dispatchEvent(printCompleteEvent);
			}
		}
		
		/**
		 * Dispatch attachments received event
		 * */
		public function dispatchLoginStatusEvent(loggedIn:Boolean, data:Object):void {
			var loggedInStatusEvent:RadiateEvent = new RadiateEvent(RadiateEvent.LOGGED_IN_STATUS);
			
			if (hasEventListener(RadiateEvent.LOGGED_IN_STATUS)) {
				loggedInStatusEvent.status = loggedIn ? LOGGED_IN : LOGGED_OUT;
				loggedInStatusEvent.data = data;
				dispatchEvent(loggedInStatusEvent);
			}
		}
		
		/**
		 * Dispatch attachments received event
		 * */
		public function dispatchAttachmentsResultsEvent(successful:Boolean, attachments:Array):void {
			var attachmentsReceivedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.ATTACHMENTS_RECEIVED, false, false, attachments);
			
			if (hasEventListener(RadiateEvent.ATTACHMENTS_RECEIVED)) {
				attachmentsReceivedEvent.successful = successful;
				attachmentsReceivedEvent.status = successful ? "ok" : "fault";
				attachmentsReceivedEvent.targets = ArrayUtil.toArray(attachments);
				dispatchEvent(attachmentsReceivedEvent);
			}
		}
		
		/**
		 * Dispatch upload attachment received event
		 * */
		public function dispatchUploadAttachmentResultsEvent(successful:Boolean, attachments:Array, data:Object):void {
			var uploadAttachmentEvent:RadiateEvent = new RadiateEvent(RadiateEvent.ATTACHMENT_UPLOADED, false, false);
			
			if (hasEventListener(RadiateEvent.ATTACHMENT_UPLOADED)) {
				uploadAttachmentEvent.successful = successful;
				uploadAttachmentEvent.status = successful ? "ok" : "fault";
				uploadAttachmentEvent.data = attachments;
				uploadAttachmentEvent.selectedItem = data;
				dispatchEvent(uploadAttachmentEvent);
			}
		}
		
		/**
		 * Dispatch login results event
		 * */
		public function dispatchLoginResultsEvent(successful:Boolean, data:Object):void {
			var loginResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.LOGIN_RESULTS);
			
			if (hasEventListener(RadiateEvent.LOGIN_RESULTS)) {
				loginResultsEvent.data = data;
				loginResultsEvent.successful = successful;
				dispatchEvent(loginResultsEvent);
			}
		}
		
		/**
		 * Dispatch logout results event
		 * */
		public function dispatchLogoutResultsEvent(successful:Boolean, data:Object):void {
			var logoutResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.LOGOUT_RESULTS);
			
			if (hasEventListener(RadiateEvent.LOGOUT_RESULTS)) {
				logoutResultsEvent.data = data;
				logoutResultsEvent.successful = successful;
				dispatchEvent(logoutResultsEvent);
			}
		}
		
		/**
		 * Dispatch register results event
		 * */
		public function dispatchRegisterResultsEvent(successful:Boolean, data:Object):void {
			var registerResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.REGISTER_RESULTS);
			
			if (hasEventListener(RadiateEvent.REGISTER_RESULTS)) {
				registerResultsEvent.data = data;
				registerResultsEvent.successful = successful;
				dispatchEvent(registerResultsEvent);
			}
		}
		
		/**
		 * Dispatch change password results event
		 * */
		public function dispatchChangePasswordResultsEvent(successful:Boolean, data:Object):void {
			var changePasswordResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.CHANGE_PASSWORD_RESULTS);
			
			if (hasEventListener(RadiateEvent.CHANGE_PASSWORD_RESULTS)) {
				changePasswordResultsEvent.data = data;
				changePasswordResultsEvent.successful = successful;
				dispatchEvent(changePasswordResultsEvent);
			}
		}
		
		/**
		 * Dispatch lost password results event
		 * */
		public function dispatchLostPasswordResultsEvent(successful:Boolean, data:Object):void {
			var lostPasswordResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.LOST_PASSWORD_RESULTS);
			
			if (hasEventListener(RadiateEvent.LOST_PASSWORD_RESULTS)) {
				lostPasswordResultsEvent.data = data;
				lostPasswordResultsEvent.successful = successful;
				dispatchEvent(lostPasswordResultsEvent);
			}
		}
		
		/**
		 * Dispatch project deleted results event
		 * */
		public function dispatchProjectDeletedEvent(successful:Boolean, data:Object):void {
			var deleteProjectResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_DELETED);
			
			if (hasEventListener(RadiateEvent.PROJECT_DELETED)) {
				deleteProjectResultsEvent.data = data;
				deleteProjectResultsEvent.successful = successful;
				deleteProjectResultsEvent.status = successful ? "ok" : "error";
				dispatchEvent(deleteProjectResultsEvent);
			}
		}
		
		/**
		 * Dispatch document deleted results event
		 * */
		public function dispatchDocumentDeletedEvent(successful:Boolean, data:Object):void {
			var deleteDocumentResultsEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_DELETED);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_DELETED)) {
				deleteDocumentResultsEvent.data = data;
				deleteDocumentResultsEvent.successful = successful;
				deleteDocumentResultsEvent.status = successful ? "ok" : "error";
				dispatchEvent(deleteDocumentResultsEvent);
			}
		}
		
		/**
		 * Dispatch asset added event
		 * */
		public function dispatchAssetAddedEvent(data:Object):void {
			var assetAddedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.ASSET_ADDED);
			
			if (hasEventListener(RadiateEvent.ASSET_ADDED)) {
				assetAddedEvent.data = data;
				dispatchEvent(assetAddedEvent);
			}
		}
		
		/**
		 * Dispatch asset removed event
		 * */
		public function dispatchAssetRemovedEvent(data:IDocumentData, successful:Boolean = true):void {
			var assetRemovedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.ASSET_REMOVED);
			
			if (hasEventListener(RadiateEvent.ASSET_REMOVED)) {
				assetRemovedEvent.data = data;
				dispatchEvent(assetRemovedEvent);
			}
		}
		
		/**
		 * Dispatch target change event
		 * */
		public function dispatchTargetChangeEvent(target:*, multipleSelection:Boolean = false):void {
			if (importingDocument) return;
			var targetChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.TARGET_CHANGE, false, false, target, null, null, multipleSelection);
			
			if (hasEventListener(RadiateEvent.TARGET_CHANGE)) {
				targetChangeEvent.selectedItem = target && target is Array ? target[0] : target;
				targetChangeEvent.targets = ArrayUtil.toArray(target);
				dispatchEvent(targetChangeEvent);
			}
		}
		
		/**
		 * Dispatch scale change event
		 * */
		public function dispatchScaleChangeEvent(target:*, scaleX:Number = NaN, scaleY:Number = NaN):void {
			var scaleChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.SCALE_CHANGE, false, false, target, null, null);
			
			if (hasEventListener(RadiateEvent.SCALE_CHANGE)) {
				scaleChangeEvent.scaleX = scaleX;
				scaleChangeEvent.scaleY = scaleY;
				dispatchEvent(scaleChangeEvent);
			}
		}
		
		/**
		 * Dispatch document size change event
		 * */
		public function dispatchDocumentSizeChangeEvent(target:*):void {
			var scaleChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_SIZE_CHANGE, false, false, target, null, null);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_SIZE_CHANGE)) {
				dispatchEvent(scaleChangeEvent);
			}
		}
		
		/**
		 * Dispatch preview event
		 * */
		public function dispatchPreviewEvent(code:String, type:String):void {
			var previewEvent:RadiateEvent = new RadiateEvent(RadiateEvent.REQUEST_PREVIEW);
			
			if (hasEventListener(RadiateEvent.REQUEST_PREVIEW)) {
				previewEvent.previewType = type;
				previewEvent.value = code;
				dispatchEvent(previewEvent);
			}
		}
		
		
		/**
		 * Dispatch code updated event. Type is usually "HTML". 
		 * */
		public function dispatchCodeUpdatedEvent(code:String, type:String, openInWindow:Boolean = false):void {
			var codeUpdatedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.CODE_UPDATED);
			
			if (hasEventListener(RadiateEvent.CODE_UPDATED)) {
				codeUpdatedEvent.previewType = type;
				codeUpdatedEvent.value = code;
				codeUpdatedEvent.openInBrowser = openInWindow;
				dispatchEvent(codeUpdatedEvent);
			}
		}
		
		/**
		 * Dispatch color selected event
		 * */
		public function dispatchColorSelectedEvent(color:uint, invalid:Boolean = false):void {
			var colorSelectedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.COLOR_SELECTED);
			
			if (hasEventListener(RadiateEvent.COLOR_SELECTED)) {
				colorSelectedEvent.color = color;
				colorSelectedEvent.invalid = invalid;
				dispatchEvent(colorSelectedEvent);
			}
		}
		
		/**
		 * Dispatch property selected event
		 * */
		public function dispatchPropertySelectedEvent(property:String, node:MetaData = null):void {
			var colorSelectedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROPERTY_SELECTED);
			
			if (hasEventListener(RadiateEvent.PROPERTY_SELECTED)) {
				colorSelectedEvent.property = property;
				colorSelectedEvent.selectedItem = node;
				dispatchEvent(colorSelectedEvent);
			}
		}
		
		/**
		 * Dispatch color preview event
		 * */
		public function dispatchColorPreviewEvent(color:uint, invalid:Boolean = false):void {
			var colorPreviewEvent:RadiateEvent = new RadiateEvent(RadiateEvent.COLOR_PREVIEW);
			
			if (hasEventListener(RadiateEvent.COLOR_PREVIEW)) {
				colorPreviewEvent.color = color;
				colorPreviewEvent.invalid = invalid;
				dispatchEvent(colorPreviewEvent);
			}
		}
		
		/**
		 * Dispatch canvas change event
		 * */
		public function dispatchCanvasChangeEvent(canvas:*, canvasBackgroundParent:*, scroller:Scroller):void {
			var targetChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.CANVAS_CHANGE);
			
			if (hasEventListener(RadiateEvent.CANVAS_CHANGE)) {
				dispatchEvent(targetChangeEvent);
			}
		}
		
		/**
		 * Dispatch tool change event
		 * */
		public function dispatchToolChangeEvent(value:ITool):void {
			var toolChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.TOOL_CHANGE);
			
			if (hasEventListener(RadiateEvent.TOOL_CHANGE)) {
				toolChangeEvent.selectedItem = target && target is Array ? target[0] : target;
				toolChangeEvent.targets = targets;
				toolChangeEvent.tool = value;
				dispatchEvent(toolChangeEvent);
			}
		}
		
		/**
		 * Dispatch target change event with a null target. 
		 * */
		public function dispatchTargetClearEvent():void {
			var targetChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.TARGET_CHANGE);
			
			if (hasEventListener(RadiateEvent.TARGET_CHANGE)) {
				dispatchEvent(targetChangeEvent);
			}
		}
		
		/**
		 * Dispatch property change event
		 * */
		public function dispatchPropertyChangeEvent(target:*, changes:Array, properties:Array, multipleSelection:Boolean = false):void {
			if (importingDocument) return;
			var propertyChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROPERTY_CHANGED, false, false, target, changes, properties, multipleSelection);
			
			if (hasEventListener(RadiateEvent.PROPERTY_CHANGED)) {
				propertyChangeEvent.properties = properties;
				propertyChangeEvent.changes = changes;
				propertyChangeEvent.multipleSelection = multipleSelection;
				propertyChangeEvent.selectedItem = target && target is Array ? target[0] : target;
				propertyChangeEvent.targets = ArrayUtil.toArray(target);
				dispatchEvent(propertyChangeEvent);
			}
		}
		
		/**
		 * Dispatch object selected event
		 * */
		public function dispatchObjectSelectedEvent(target:*):void {
			var objectSelectedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.OBJECT_SELECTED, false, false, target);
			
			if (hasEventListener(RadiateEvent.OBJECT_SELECTED)) {
				dispatchEvent(objectSelectedEvent);
			}
		}
		
		/**
		 * Dispatch add items event
		 * */
		public function dispatchAddEvent(target:*, changes:Array, properties:Array, multipleSelection:Boolean = false):void {
			if (importingDocument) return;
			var event:RadiateEvent = new RadiateEvent(RadiateEvent.ADD_ITEM, false, false, target, changes, properties, multipleSelection);
			var length:int = changes ? changes.length : 0;
			
			if (hasEventListener(RadiateEvent.ADD_ITEM)) {
				event.properties = properties;
				event.changes = changes;
				event.multipleSelection = multipleSelection;
				event.selectedItem = target && target is Array ? target[0] : target;
				event.targets = ArrayUtil.toArray(target);
				
				for (var i:int;i<length;i++) {
					if (changes[i] is AddItems) {
						event.addItemsInstance = changes[i];
						event.moveItemsInstance = changes[i];
					}
				}
				dispatchEvent(event);
			}
		}
		
		/**
		 * Dispatch add items event
		 * */
		public function dispatchMoveEvent(target:*, changes:Array, properties:Array, multipleSelection:Boolean = false):void {
			if (importingDocument) return;
			var event:RadiateEvent = new RadiateEvent(RadiateEvent.MOVE_ITEM, false, false, target, changes, properties, multipleSelection);
			var length:int = changes ? changes.length : 0;
			
			if (hasEventListener(RadiateEvent.MOVE_ITEM)) {
				event.properties = properties;
				event.changes = changes;
				event.multipleSelection = multipleSelection;
				event.selectedItem = target && target is Array ? target[0] : target;
				event.targets = ArrayUtil.toArray(target);
				
				for (var i:int;i<length;i++) {
					if (changes[i] is AddItems) {
						event.addItemsInstance = changes[i];
						event.moveItemsInstance = changes[i];
					}
				}
				dispatchEvent(event);
			}
		}
		
		/**
		 * Dispatch remove items event
		 * */
		public function dispatchRemoveItemsEvent(target:*, changes:Array, properties:*, multipleSelection:Boolean = false):void {
			var event:RadiateEvent = new RadiateEvent(RadiateEvent.REMOVE_ITEM, false, false, target, changes, properties, multipleSelection);
			var length:int = changes ? changes.length : 0;
			
			if (hasEventListener(RadiateEvent.REMOVE_ITEM)) {
				event.properties = properties;
				event.changes = changes;
				event.multipleSelection = multipleSelection;
				event.selectedItem = target && target is Array ? target[0] : target;
				event.targets = ArrayUtil.toArray(target);
				
				for (var i:int;i<length;i++) {
					if (changes[i] is AddItems) {
						event.addItemsInstance = changes[i];
						event.moveItemsInstance = changes[i];
					}
				}
				dispatchEvent(event);
			}
		}
		
		/**
		 * Dispatch to invoke property edit event
		 * */
		public function dispatchTargetPropertyEditEvent(target:Object, changes:Array, properties:Array, multipleSelection:Boolean = false):void {
			var propertyEditEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROPERTY_EDIT, false, false, target, changes, properties, null, multipleSelection);
			
			if (hasEventListener(RadiateEvent.PROPERTY_EDIT)) {
				dispatchEvent(propertyEditEvent);
			}
		}
		
		/**
		 * Dispatch document change event
		 * */
		public function dispatchDocumentChangeEvent(document:IDocument):void {
			var documentChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_CHANGE, false, false, document);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_CHANGE)) {
				dispatchEvent(documentChangeEvent);
			}
		}
		
		/**
		 * Dispatch document rename event
		 * */
		public function dispatchDocumentRenameEvent(document:IDocument, name:String):void {
			var documentRenameEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_RENAME, false, false, document);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_RENAME)) {
				dispatchEvent(documentRenameEvent);
			}
		}
		
		/**
		 * Dispatch project rename event
		 * */
		public function dispatchProjectRenameEvent(project:IProject, name:String):void {
			var projectRenameEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_RENAME, false, false, project);
			
			if (hasEventListener(RadiateEvent.PROJECT_RENAME)) {
				dispatchEvent(projectRenameEvent);
			}
		}
		
		/**
		 * Dispatch documents set
		 * */
		public function dispatchDocumentsSetEvent(documents:Array):void {
			var documentChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENTS_SET, false, false, documents);
			
			if (hasEventListener(RadiateEvent.DOCUMENTS_SET)) {
				dispatchEvent(documentChangeEvent);
			}
		}
		
		/**
		 * Dispatch document opening event
		 * */
		public function dispatchDocumentOpeningEvent(document:IDocument, isPreview:Boolean = false):Boolean {
			var documentOpeningEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_OPENING, false, true, document);
			var dispatched:Boolean;
			
			if (hasEventListener(RadiateEvent.DOCUMENT_OPENING)) {
				dispatched = dispatchEvent(documentOpeningEvent);
			}
			
			return dispatched;
		}
		
		/**
		 * Dispatch document open event
		 * */
		public function dispatchDocumentOpenEvent(document:IDocument):void {
			var documentOpenEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_OPEN, false, false);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_OPEN)) {
				documentOpenEvent.selectedItem = document;
				dispatchEvent(documentOpenEvent);
			}
		}
		
		/**
		 * Dispatch document removed event
		 * */
		public function dispatchDocumentRemovedEvent(document:IDocument, successful:Boolean = true):void {
			var documentRemovedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_REMOVED, false, false);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_REMOVED)) {
				documentRemovedEvent.successful = successful;
				documentRemovedEvent.selectedItem = document;
				dispatchEvent(documentRemovedEvent);
			}
		}
		
		/**
		 * Dispatch document save as complete event
		 * */
		public function dispatchProjectSavedEvent(project:IProject):void {
			var projectSaveEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_SAVED, false, false);
			
			if (hasEventListener(RadiateEvent.PROJECT_SAVED)) {
				
				projectSaveEvent.selectedItem = project;
				dispatchEvent(projectSaveEvent);
			}
		}
		
		/**
		 * Dispatch document save complete event
		 * */
		public function dispatchDocumentSaveCompleteEvent(document:IDocument):void {
			var documentSaveAsCompleteEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_SAVE_COMPLETE, false, false, document);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_SAVE_COMPLETE)) {
				dispatchEvent(documentSaveAsCompleteEvent);
			}
		}
		
		/**
		 * Dispatch document not saved event
		 * */
		public function dispatchDocumentSaveFaultEvent(document:IDocument):void {
			var documentSaveFaultEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_SAVE_FAULT, false, false, document);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_SAVE_FAULT)) {
				dispatchEvent(documentSaveFaultEvent);
			}
		}
		
		/**
		 * Dispatch document save as cancel event
		 * */
		public function dispatchDocumentSaveAsCancelEvent(document:IDocument):void {
			var documentSaveAsCancelEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_SAVE_AS_CANCEL, false, false, document);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_SAVE_AS_CANCEL)) {
				dispatchEvent(documentSaveAsCancelEvent);
			}
		}
		
		
		/**
		 * Dispatch document add event
		 * */
		public function dispatchDocumentAddedEvent(document:IDocument):void {
			var documentAddedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.DOCUMENT_ADDED, false, false, document, null, null);
			
			if (hasEventListener(RadiateEvent.DOCUMENT_ADDED)) {
				dispatchEvent(documentAddedEvent);
			}
		}
		
		/**
		 * Dispatch project closing event
		 * */
		public function dispatchProjectClosingEvent(project:IProject):void {
			var projectClosingEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_CLOSING, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_CLOSING)) {
				dispatchEvent(projectClosingEvent);
			}
		}
		
		/**
		 * Dispatch project closed event
		 * */
		public function dispatchProjectOpenedEvent(project:IProject):void {
			var projectOpenedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_OPENED, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_OPENED)) {
				dispatchEvent(projectOpenedEvent);
			}
		}
		
		/**
		 * Dispatch project closed event
		 * */
		public function dispatchProjectClosedEvent(project:IProject):void {
			var projectClosedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_CLOSED, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_CLOSED)) {
				dispatchEvent(projectClosedEvent);
			}
		}
		
		/**
		 * Dispatch project removed event
		 * */
		public function dispatchProjectRemovedEvent(project:IProject):void {
			var projectRemovedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_REMOVED, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_REMOVED)) {
				dispatchEvent(projectRemovedEvent);
			}
		}
		
		/**
		 * Dispatch project change event
		 * */
		public function dispatchProjectChangeEvent(project:IProject, multipleSelection:Boolean = false):void {
			var projectChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_CHANGE, false, false, project, null, null, multipleSelection);
			
			if (hasEventListener(RadiateEvent.PROJECT_CHANGE)) {
				dispatchEvent(projectChangeEvent);
			}
		}
		
		/**
		 * Dispatch projects set event
		 * */
		public function dispatchProjectsSetEvent(projects:Array, multipleSelection:Boolean = false):void {
			var projectChangeEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECTS_SET, false, false, projects, null, null, multipleSelection);
			
			if (hasEventListener(RadiateEvent.PROJECTS_SET)) {
				dispatchEvent(projectChangeEvent);
			}
		}
		
		/**
		 * Dispatch project created event
		 * */
		public function dispatchProjectAddedEvent(project:IProject):void {
			var projectCreatedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_ADDED, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_ADDED)) {
				dispatchEvent(projectCreatedEvent);
			}
		}
		
		/**
		 * Dispatch project created event
		 * */
		public function dispatchProjectCreatedEvent(project:IProject):void {
			var projectCreatedEvent:RadiateEvent = new RadiateEvent(RadiateEvent.PROJECT_CREATED, false, false, project, null, null);
			
			if (hasEventListener(RadiateEvent.PROJECT_CREATED)) {
				dispatchEvent(projectCreatedEvent);
			}
		}
		
		/**
		 * Dispatch a history change event
		 * */
		public function dispatchHistoryChangeEvent(newIndex:int, oldIndex:int):void {
			var event:RadiateEvent = new RadiateEvent(RadiateEvent.HISTORY_CHANGE);
			
			if (hasEventListener(RadiateEvent.HISTORY_CHANGE)) {
				event.newIndex = newIndex;
				event.oldIndex = oldIndex;
				event.historyEventItem = getHistoryItemAtIndex(newIndex);
				dispatchEvent(event);
			}
		}
		
		/**
		 * Sets the logging target
		 * */
		public static function setLoggingTarget(target:AbstractTarget = null, category:String = null, consoleObject:Object = null):void {
			
			// Log only messages for the classes in the mx.rpc.* and 
			// mx.messaging packages.
			//logTarget.filters=["mx.rpc.*","mx.messaging.*"];
			//var filters:Array = ["mx.rpc.*", "mx.messaging.*"];
			//var filters:Array = ["mx.rpc.*", "mx.messaging.*"];
			
			// Begin logging.
			if (target) {
				logTarget = target;
				//logTarget.filters = filters;
				logTarget.level = LogEventLevel.ALL;
				Log.addTarget(target);
			}
			
			// set reference to logger
			if (category) {
				log = Log.getLogger(category);
			}
			else {
				log = Log.getLogger(RADIATE_LOG);
			}
			
			if (consoleObject) {
				console = consoleObject;
			}
			
		}
		
		/**
		 * Creates the list of components and tools.
		 * */
		public static function initialize():void {
			var componentsXML:XML 	= new XML(new Radii8LibrarySparkAssets.sparkManifestDefaults());
			var toolsXML:XML 		= new XML(new Radii8LibraryToolAssets.toolsManifestDefaults());
			var inspectorsXML:XML 	= new XML(new Radii8LibraryInspectorAssets.inspectorsManifestDefaults());
			var devicesXML:XML		= new XML(new Radii8LibraryDeviceAssets.devicesManifestDefaults());
			
			createSettingsData();

			createSavedData();
			
			createComponentList(componentsXML);
			
			createInspectorsList(inspectorsXML);
			
			createToolsList(toolsXML);
			
			createDevicesList(devicesXML);
		}
		
		/**
		 * Startup 
		 * */
		public static function startup():void {
			
			//ExternalInterface.call("Radiate.getInstance");
			ExternalInterface.call("Radiate.instance.setFlashInstance", ExternalInterface.objectID);
			
			//instance.getLoggedInStatus();
		}
		
		/**
		 * Creates the list of components.
		 * */
		public static function createComponentList(xml:XML):void {
			var length:uint;
			var items:XMLList;
			var className:String;
			var skinClassName:String;
			var inspectors:Array;
			var hasDefinition:Boolean;
			var classType:Object;
			var includeItem:Boolean;
			var attributes:XMLList;
			var attributesLength:int;
			var defaults:Object;
			var propertyName:String;
			var item:XML;
			
			
			// get list of component classes 
			items = XML(xml).component;
			
			length = items.length();
			
			for (var i:int;i<length;i++) {
				item = items[i];
				
				var name:String = String(item.id);
				className = item.attribute("class");
				skinClassName = item.attribute("skinClass");
				//inspectors = item.inspector;
				
				includeItem = item.attribute("include")=="false" ? false : true;
				
				
				
				// check that definitions exist in domain
				// skip any support classes
				if (className.indexOf("mediaClasses")==-1 && 
					className.indexOf("gridClasses")==-1 &&
					className.indexOf("windowClasses")==-1 &&
					className.indexOf("supportClasses")==-1) {
					
					hasDefinition = ApplicationDomain.currentDomain.hasDefinition(className);
					
					if (hasDefinition) {
						classType = ApplicationDomain.currentDomain.getDefinition(className);
						
						// need to check if we have the skin as well
						
						//hasDefinition = ApplicationDomain.currentDomain.hasDefinition(skinClassName);
						
						if (hasDefinition) {
							
							// get default values
							if (item.defaults) {
								attributes = item.defaults.attributes();
								attributesLength = attributes.length();
								defaults = {};
								
								for each (var value:Object in attributes) {
									propertyName = String(value.name());
									
									if (propertyName=="dataProvider") {
										var array:Array = String(value).split(",");
										defaults[propertyName] = new ArrayCollection(array);
									}
									else {
										defaults[propertyName] = String(value);
									}
								}
							}
							
							addComponentType(item.@id, className, classType, inspectors, null, defaults, null, includeItem);
						}
						else {
							log.error("Component skin class, '" + skinClassName + "' not found for '" + className + "'.");
						}
					}
					else {
						log.error("Component class not found: " + className);
					}
					
				}
				else {
					// delete support classes
					// may need to refactor why we are including them in the first place
					delete items[i];
					length--;
				}
			}
			
			// componentDescriptions should now be populated
		}
		
		/**
		 * Creates the list of inspectors.
		 * */
		public static function createInspectorsList(xml:XML):void {
			var length:uint;
			var inspectorsLength:uint;
			var items:XMLList;
			var className:String;
			var skinClassName:String;
			var inspectorClassName:String;
			var hasDefinition:Boolean;
			var classType:Object;
			var includeItem:Boolean;
			var attributes:XMLList;
			var attributesLength:int;
			var defaults:Object;
			var propertyName:String;
			var item:XML;
			var inspectorItems:XMLList;
			var inspector:XML;
			var inspectableClass:InspectableClass;
			var inspectorData:InspectorData;
			
			
			// get list of inspector classes 
			items = XML(xml).item;
			
			length = items.length();
			
			// add inspectable classes to the dictionary
			for (var i:int;i<length;i++) {
				inspectableClass = new InspectableClass(items[i]);
				className = inspectableClass.className;
				
				if (inspectableClassesDictionary[className]==null) {
					inspectableClassesDictionary[className] = inspectableClass;
				}
				else {
					log.warn("Inspectable class, '" + className + "', was listed more than once during import.");
				}
					
			}
			
			// check that definitions exist in domain
			for each (inspectableClass in inspectableClassesDictionary) {
			
				length = inspectableClass.inspectors.length;
				j = 0;
				
				for (var j:int;j<length;j++) {
					inspectorData = inspectableClass.inspectors[j];
					className = inspectorData.className;
					
					if (inspectorsDictionary[className]==null) {
						
						hasDefinition = ApplicationDomain.currentDomain.hasDefinition(className);
						
						if (hasDefinition) {
							classType = ApplicationDomain.currentDomain.getDefinition(className);
						}
						else {
							log.error("Inspector class not found: " + className);
						}
						
						// not passing in classType now since we may load it in later dynamically
						addInspectorType(inspectorData.name, className, null, inspectorData.icon, defaults);
					}
					else {
						//log.warn("Inspector class: " + className + ", is already in the dictionary");
					}
				}
			}
			
			// inspectorsInstancesDictionary should now be populated
		}
		
		
		/**
		 * Creates the list of tools.
		 * */
		public static function createToolsList(xml:XML):void {
			var inspectorClassName:String;
			var hasDefinition:Boolean;
			var toolClassDefinition:Object;
			var inspectorClassDefinition:Object;
			var inspectorClassFactory:ClassFactory;
			var toolClassFactory:ClassFactory;
			var items:XMLList;
			var className:String;
			var includeItem:Boolean;
			var attributes:XMLList;
			var length:uint;
			var attributesLength:int;
			var defaults:Object;
			var propertyName:String;
			var toolInstance:ITool;
			var inspectorInstance:UIComponent;
			var name:String;
			var cursorItems:XMLList;
			var cursorItem:XML;
			var cursorName:String;
			var cursors:Dictionary;
			var cursorsCount:int;
			var cursorData:MouseCursorData;
			var cursorBitmapDatas:Vector.<BitmapData>;
			var cursorBitmap:Bitmap;
			var cursorClass:Class;
			var cursorID:String;
			var cursorX:int;
			var cursorY:int;
			var item:XML;
			
			// get list of tool classes 
			items = XML(xml).tool;
			
			length = items.length();
			
			for (var i:int;i<length;i++) {
				item = items[i];
				
				name = String(item.id);
				className = item.attribute("class");
				inspectorClassName = item.attribute("inspector");
				cursorItems = item..cursor;
				
				includeItem = item.attribute("include")=="false" ? false : true;
				
				if (!includeItem) continue;
				
				hasDefinition = ApplicationDomain.currentDomain.hasDefinition(className);
				
				if (hasDefinition) {
					toolClassDefinition = ApplicationDomain.currentDomain.getDefinition(className);
					
					
					// get default values
					if (item.defaults) {
						attributes = item.defaults.attributes();
						attributesLength = attributes.length();
						defaults = {};
						
						for each (var value:Object in attributes) {
							propertyName = String(value.name());
							
							if (propertyName=="dataProvider") {
								defaults[propertyName] = new ArrayCollection(String(value).split(","));
							}
							else {
								defaults[propertyName] = String(value);
							}
						}
					}
					
					// create tool
					toolClassFactory = new ClassFactory(toolClassDefinition as Class);
					toolClassFactory.properties = defaults;
					toolInstance = toolClassFactory.newInstance();
					
					
					// create inspector
					if (inspectorClassName!="") {
						hasDefinition = ApplicationDomain.currentDomain.hasDefinition(inspectorClassName);
						
						if (hasDefinition) {
							inspectorClassDefinition = ApplicationDomain.currentDomain.getDefinition(inspectorClassName);
							
							// Create tool inspector
							inspectorClassFactory = new ClassFactory(inspectorClassDefinition as Class);
							//classFactory.properties = defaults;
							inspectorInstance = inspectorClassFactory.newInstance();
					
						}
						else {
							var errorMessage:String = "Could not find inspector, '" + inspectorClassName + "' for tool, '" + className + "'. ";
							errorMessage += "You may need to add a reference to it in RadiateReferences.";
							log.error(errorMessage);
						}
					}
					
					
					cursorsCount = cursorItems.length();
					
					if (cursorsCount>0) {
						cursors = new Dictionary(false);
					}

					// create mouse cursors
					for (var j:int=0;j<cursorsCount;j++) {
						cursorItem = cursorItems[j];
						cursorName = cursorItem.@name.toString();
						cursorX = int(cursorItem.@x.toString());
						cursorY = int(cursorItem.@y.toString());
						cursorID = cursorName != "" ? className + "." + cursorName : className;
			
						// Create a MouseCursorData object 
						cursorData = new MouseCursorData();
						
						// Specify the hotspot 
						cursorData.hotSpot = new Point(cursorX, cursorY); 
						
						// Pass the cursor bitmap to a BitmapData Vector 
						cursorBitmapDatas = new Vector.<BitmapData>(1, true); 
						
						// Create the bitmap cursor 
						// The bitmap must be 32x32 pixels or smaller, due to an OS limitation
						//CursorClass = Radii8LibraryToolAssets.EyeDropper;
						
						if (cursorName) {
							cursorClass = toolClassDefinition[cursorName];
						}
						else {
							cursorClass = toolClassDefinition["Cursor"];
						}
						
						cursorBitmap = new cursorClass();
						
						// Pass the value to the bitmapDatas vector 
						cursorBitmapDatas[0] = cursorBitmap.bitmapData;
						
						// Assign the bitmap to the MouseCursor object 
						cursorData.data = cursorBitmapDatas;
						
						// Register the MouseCursorData to the Mouse object with an alias 
						Mouse.registerCursor(cursorID, cursorData);
						
						cursors[cursorName] = {cursorData:cursorData, id:cursorID};
					}
					
					if (cursorsCount>0) {
						mouseCursors[className] = cursors;
					}
					
					//trace("tool cursors:", cursors);
					var toolDescription:ComponentDescription = addToolType(item.@id, className, toolClassDefinition, toolInstance, inspectorClassName, null, defaults, null, cursors);
					//trace("tool cursors:", toolDescription.cursors);
				}
				else {
					//trace("Tool class not found: " + classDefinition);
					log.error("Tool class not found: " + toolClassDefinition);
				}
				
			}
			
			// toolDescriptions should now be populated
		}
		
		/**
		 * Creates the list of devices.
		 * */
		public static function createDevicesList(xml:XML):void {
			var includeItem:Boolean;
			var items:XMLList;
			var length:uint;
			var name:String;
			var item:XML;
			var device:Device;
			var type:String;
			
			const RES_WIDTH:String = "resolutionWidth";
			const RES_HEIGHT:String = "resolutionHeight";
			const USABLE_WIDTH_PORTRAIT:String = "usableWidthPortrait";
			const USABLE_HEIGHT_PORTRAIT:String = "usableHeightPortrait";
			const USABLE_WIDTH_LANDSCAPE:String = "usableWidthLandscape";
			const USABLE_HEIGHT_LANDSCAPE:String = "usableHeightLandscape";
			
			
			// get list of device classes 
			items = XML(xml).size;
			
			length = items.length();
			
			for (var i:int;i<length;i++) {
				item = items[i];
				
				name = item.attribute("name");
				type = item.attribute("type");
				
				device = new Device();
				device.name = name;
				device.type = type;
				
				if (type=="device") {
					device.ppi 					= item.attribute("ppi");
					
					device.resolutionWidth 		= item.attribute(RES_WIDTH);
					device.resolutionHeight 	= item.attribute(RES_HEIGHT);
					device.usableWidthPortrait 	= item.attribute(USABLE_WIDTH_PORTRAIT);
					device.usableHeightPortrait = item.attribute(USABLE_HEIGHT_PORTRAIT);
					device.usableWidthLandscape = item.attribute(USABLE_WIDTH_LANDSCAPE);
					device.usableHeightLandscape = item.attribute(USABLE_HEIGHT_LANDSCAPE);
				}
				else if (type=="screen") {
					device.ppi 					= item.attribute("ppi");
					device.resolutionWidth 		= item.attribute(RES_WIDTH);
					device.resolutionHeight 	= item.attribute(RES_HEIGHT);
					continue;
				}
				
				includeItem = item.attribute("include")=="false" ? false : true;
				
				deviceCollections.addItem(device);
				
			}
			
			// deviceDescriptions should now be populated
		}
		
		/**
		 * Helper method to get the ID of the mouse cursor by name.
		 * 
		 * */
		public function getMouseCursorID(tool:ITool, name:String = "Cursor"):String {
			var component:ComponentDescription = getToolDescription(tool);
			
			
			if (component.cursors && component.cursors[name]) {
				return component.cursors[name].id;
			}
			
			return null;
		}
		
		//----------------------------------
		//  target
		//----------------------------------
		
		/**
		 * Use setTarget() or setTargets() method to set the target. 
		 * */
		public function get target():Object {
			if (_targets.length > 0)
				return _targets[0];
			else
				return null;
		}
		
		/**
		 *  @private
		 */
		/*[Bindable]
		public function set target(value:Object):void {
			if (_targets.length == 1 && target==value) return;
			
			_targets.splice(0);
			
			if (value) {
				_targets[0] = value;
			}
		}*/

		
		//----------------------------------
		//  targets
		//----------------------------------
		
		/**
		 *  @private
		 *  Storage for the targets property.
		 */
		private var _targets:Array = [];
		
		/**
		 * Selected targets
		 * */
		public function get targets():Array {
			return _targets;
		}
		
		/**
		 * Use setTargets() to set the targets
		 *  @private
		 * */
		/*public function set targets(value:Array):void {
			// remove listeners from previous targets
			var n:int = _targets.length;
			
			for (var i:int = n - 1; i >= 0; i--) {
				if (_targets[i] == null) {
					continue;
				}
				
				//removeHandlers(_targets[i]);
			}
			
			// Strip out null values.
			// Binding will trigger again when the null targets are created.
			n = value.length;
			
			for (i = n - 1; i >= 0; i--) {
				if (value[i] == null) {
					value.splice(i,1);
					continue;
				}
				
				//addHandlers(value[i]);
			}
			
			_targets = value;
			
		}*/
		
		//----------------------------------
		//  project
		//----------------------------------
		
		private var _selectedProject:IProject;
		
		/**
		 * Reference to the current project
		 * */
		public function get selectedProject():IProject {
			return _selectedProject;
		}
		
		/**
		 *  @private
		 */
		[Bindable(event="projectChange")]
		public function set selectedProject(value:IProject):void {
			if (value==_selectedProject) return;
			_selectedProject = value;
			
		}
		
		//----------------------------------
		//  document
		//----------------------------------
		
		private var _documentsTabNavigator:TabNavigator;

		/**
		 * Reference to the tab navigator that creates documents
		 * */
		public function get documentsTabNavigator():TabNavigator {
			return _documentsTabNavigator;
		}

		/**
		 * @private
		 */
		public function set documentsTabNavigator(value:TabNavigator):void {
			_documentsTabNavigator = value;
		}

		
		/**
		 * Reference to the tab that the document belongs to
		 * */
		public var documentsContainerDictionary:Dictionary = new Dictionary(true);
		
		/**
		 * Reference to the tab that the document preview belongs to
		 * */
		public var documentsPreviewDictionary:Dictionary = new Dictionary(true);
		
		private var _selectedDocument:IDocument;
		
		/**
		 * Get the current document.
		 * */
		public function get selectedDocument():IDocument {
			return _selectedDocument;
		}
		
		/**
		 *  @private
		 */
		[Bindable(event="documentChange")]
		public function set selectedDocument(value:IDocument):void {
			if (value==_selectedDocument) return;
			_selectedDocument = value;
		}
		
		/**
		 * Templates for creating new projects or documents
		 * */
		[Bindable]
		public var templates:Array;
		
		//----------------------------------
		//  documents
		//----------------------------------
		
		/**
		 *  @private
		 *  Storage for the documents property.
		 */
		private var _documents:Array = [];
		
		/**
		 * Selected documents
		 * */
		public function get documents():Array {
			return _documents;
		}
		
		/**
		 * Selected documents
		 *  @private
		 * */
		[Bindable]
		public function set documents(value:Array):void {
			// the following comments are old possibly irrelevant...
			// remove listeners from previous documents
			var n:int = _documents.length;
			
			for (var i:int = n - 1; i >= 0; i--) {
				if (_documents[i] == null) {
					continue;
				}
				
				//removeHandlers(_documents[i]);
			}
			
			// Strip out null values.
			// Binding will trigger again when the null documents are created.
			n = value.length;
			
			for (i = n - 1; i >= 0; i--) {
				if (value[i] == null) {
					value.splice(i,1);
					continue;
				}
				
				//addHandlers(value[i]);
			}
			
			_documents = value;
			
		}
		
		
		//----------------------------------
		//  projects
		//----------------------------------
		
		
		/**
		 * Reference to the projects belongs to
		 * */
		public var projectsDictionary:Dictionary = new Dictionary(true);
		
		/**
		 *  @private
		 *  Storage for the projects property.
		 */
		private var _projects:Array = [];
		
		/**
		 * Selected projects
		 * */
		public function get projects():Array {
			return _projects;
		}
		
		/**
		 * Selected projects
		 *  @private
		 * */
		[Bindable]
		public function set projects(value:Array):void {
			_projects = value;
			
		}
		
		private var _attachments:Array = [];

		/**
		 * Attachments
		 * */
		[Bindable]
		public function get attachments():Array {
			return _attachments;
		}

		public function set attachments(value:Array):void {
			_attachments = value;
		}
		
		private var _assets:ArrayCollection = new ArrayCollection();

		/**
		 * Assets
		 * */
		[Bindable]
		public function get assets():ArrayCollection {
			return _assets;
		}

		public function set assets(value:ArrayCollection):void {
			_assets = value;
		}

		
		private var _toolLayer:IVisualElementContainer;

		/**
		 * Container that tools can draw too
		 * */
		public function get toolLayer():IVisualElementContainer {
			return _toolLayer;
		}

		/**
		 * @private
		 */
		public function set toolLayer(value:IVisualElementContainer):void {
			_toolLayer = value;
		}

		
		/**
		 * Default log target
		 * */
		public static var defaultLogTarget:AbstractTarget = new RadiateLogTarget();
		
		/**
		 * Attempt to support a console
		 * */
		public static var logTarget:AbstractTarget;
		
		private static var _log:ILogger;
		
		private static var _console:Object;
		
		public static var SETTINGS_DATA_NAME:String = "settingsData";
		public static var SAVED_DATA_NAME:String 	= "savedData";
		public static var WP_HOST:String = "http://www.radii8.com";
		public static var WP_PATH:String = "/r8m/";
		public static var WP_USER_PATH:String = "";
		public static var DEFAULT_DOCUMENT_WIDTH:int = 800;
		public static var DEFAULT_DOCUMENT_HEIGHT:int = 792;
		
		public static function getWPURL():String {
			return WP_HOST + WP_PATH + WP_USER_PATH;
		}
		
		/**
		 * Is true when preview is visible. This is manually set. 
		 * Needs refactoring. 
		 * */
		public var isPreviewVisible:Boolean;
		
		/**
		 * Settings 
		 * */
		public static var settings:Settings;
		
		/**
		 * Settings 
		 * */
		public static var savedData:SavedData;
		
		/**
		 * Collection of mouse cursors that can be added or removed to 
		 * */
		[Bindable]
		public static var mouseCursors:Dictionary = new Dictionary(true);
		
		//----------------------------------
		//
		//  Device Management
		// 
		//----------------------------------
		
		/**
		 * Collection of devices
		 * */
		[Bindable]
		public static var deviceCollections:ArrayCollection = new ArrayCollection();
		
		
		//----------------------------------
		//
		//  Tools Management
		// 
		//----------------------------------
		
		public var _selectedTool:ITool;
		
		/**
		 * Get selected tool.
		 * */
		public function get selectedTool():ITool {
			return _selectedTool;
		}
		
		/**
		 * Collection of tools that can be added or removed to 
		 * */
		[Bindable]
		public static var toolsDescriptions:ArrayCollection = new ArrayCollection();
		
		/**
		 * Add the named tool class to the list of available tools.
		 * 
		 * Not sure if we should create an instance here or earlier or later. 
		 * */
		public static function addToolType(name:String, className:String, classType:Object, instance:ITool, inspectorClassName:String, icon:Object = null, defaultProperties:Object=null, defaultStyles:Object=null, cursors:Dictionary = null):ComponentDescription {
			var definition:ComponentDescription;
			var length:uint = toolsDescriptions.length;
			var item:ComponentDescription;
			
			for (var i:uint;i<length;i++) {
				item = toolsDescriptions.getItemAt(i) as ComponentDescription;
				
				// check if it exists already
				if (item && item.classType==classType) {
					return item;
					//return false;
				}
			}
			
			definition = new ComponentDescription();
			
			definition.name = name;
			definition.icon = icon;
			definition.className = className;
			definition.classType = classType;
			definition.defaultStyles = defaultStyles;
			definition.defaultProperties = defaultProperties;
			definition.instance = instance;
			definition.inspectorClassName = inspectorClassName;
			definition.cursors = cursors;
			
			toolsDescriptions.addItem(definition);
			
			return definition;
		}
		
		/**
		 * Sets the selected tool
		 * */
		public function setTool(value:ITool, dispatchEvent:Boolean = true, cause:String = ""):void {
			
			if (selectedTool) {
				selectedTool.disable();
			}
			
			_selectedTool = value;
			
			if (selectedTool) {
				selectedTool.enable();
			}
			
			if (dispatchEvent) {
				instance.dispatchToolChangeEvent(selectedTool);
			}
			
		}
		
		/**
		 * Get tool description.
		 * */
		public function getToolDescription(instance:ITool):ComponentDescription {
			var length:int = toolsDescriptions.length;
			var componentDescription:ComponentDescription;
			
			for (var i:int;i<length;i++) {
				componentDescription = ComponentDescription(toolsDescriptions.getItemAt(i));
				
				if (componentDescription.instance==instance) {
					return componentDescription;
				}
			}
			
			return null;
		}
		
		/**
		 * Get tool by name.
		 * */
		public function getToolByName(name:String):ComponentDescription {
			var length:int = toolsDescriptions.length;
			var componentDescription:ComponentDescription;
			
			for (var i:int;i<length;i++) {
				componentDescription = ComponentDescription(toolsDescriptions.getItemAt(i));
				
				if (componentDescription.className==name) {
					return componentDescription;
				}
			}
			
			return null;
		}
		
		/**
		 * Get tool by type.
		 * */
		public function getToolByType(type:Class):ComponentDescription {
			var length:int = toolsDescriptions.length;
			var componentDescription:ComponentDescription;
			
			for (var i:int;i<length;i++) {
				componentDescription = ComponentDescription(toolsDescriptions.getItemAt(i));
				
				if (componentDescription.classType==type) {
					return componentDescription;
				}
			}
			
			return null;
		}
		
		//----------------------------------
		//
		//  Inspector Management
		// 
		//----------------------------------
		
		/**
		 * Collection of inspectors that can be added or removed to 
		 * */
		[Bindable]
		public static var inspectorsDescriptions:ArrayCollection = new ArrayCollection();
		
		/**
		 * Dictionary of classes that have inspectors
		 * */
		[Bindable]
		public static var inspectableClassesDictionary:Dictionary = new Dictionary();
		
		/**
		 * Dictionary of instances of inspectors searched by class name
		 * */
		[Bindable]
		public static var inspectorsDictionary:Dictionary = new Dictionary();
		
		/**
		 * Add the named inspector class to the list of available inspectors
		 * */
		public static function addInspectorType(name:String, className:String, classType:Object, icon:Object = null, defaults:Object=null):Boolean {
			var inspectorData:InspectorData;
			
			if (inspectorsDictionary[className]==null) {
				inspectorData = new InspectorData();
				inspectorData.name = name==null ? className : name;
				inspectorData.className = className;
				inspectorData.classType = classType;
				inspectorData.icon = icon;
				inspectorData.defaults = defaults;
				inspectorsDictionary[className] = inspectorData;
			}
			
			
			return true;
		}
		
		/**
		 * Gets inspector classes or null if the definition is not found.
		 * */
		public function getInspectableClassData(className:String):InspectableClass {
			var inspectableClass:InspectableClass = inspectableClassesDictionary[className];
			
			return inspectableClass;
		}
		
		/**
		 * Gets an instance of the inspector class or null if the definition is not found.
		 * */
		public function getInspectorInstance(className:String):IInspector {
			var inspectorData:InspectorData = inspectorsDictionary[className];
			
			if (inspectorData) {
				if (inspectorData.instance) {
					return inspectorData.instance;
				}
				
				var instance:IInspector = inspectorData.getInstance();
				
				return instance;
			
			}

			return null;
		}
		
		/**
		 * Gets an instance of the inspector class or null if the definition is not found.
		 * */
		public function getInspector(target:Object, domain:ApplicationDomain = null):IInspector {
			var className:String;
			
			if (target) {
				className = ClassUtils.getQualifiedClassName(target);
				
				var instance:IInspector = getInspectorInstance(className);
				
				return instance;
			}

			return null;
		}
		
		/**
		 * Gets array of inspector data for the given fully qualified class or object
		 * */
		public function getInspectors(target:Object):Array {
			var className:String;
			var inspectors:Array;
			var inspectorDataArray:Array;
			var inspectableClass:InspectableClass;
			var length:int;
			
			if (target==null) return [];
			
			if (target is Object) {
				className = ClassUtils.getQualifiedClassName(target);
				
				if (target is Application) {
					className = ClassUtils.getSuperClassName(target);
				}
			}
			
			if (target is String) {
				className = String(target);
			}
			
			className = className ? className.split("::").join(".") : className;
			
			inspectableClass = getInspectableClassData(className);
			
			if (inspectableClass) {
				return inspectableClass.inspectors;
			}

			return [];
		}
		
		//----------------------------------
		//
		//  Scale Management
		// 
		//----------------------------------
		
		/**
		 * Stops on the scale
		 * */
		public var scaleStops:Array = [.05,.0625,.0833,.125,.1666,.25,.333,.50,.667,1,1.25,1.50,1.75,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
		
		/**
		 * Increases the zoom of the target application to next value 
		 * */
		public function increaseScale(valueFrom:Number = NaN, dispatchEvent:Boolean = true):void {
			var newScale:Number;
			var currentScale:Number;
			
		
			if (isNaN(valueFrom)) {
				currentScale = Number(DisplayObject(selectedDocument.instance).scaleX.toFixed(4));
			}
			else {
				currentScale = valueFrom;
			}
			
			//newScale = DisplayObject(document).scaleX;
			
			for (var i:int=0;i<scaleStops.length;i++) {
				if (currentScale<scaleStops[i]) {
					newScale = scaleStops[i];
					break;
				}
			}
			
			if (i==scaleStops.length-1) {
				newScale = scaleStops[i];
			}
			
			newScale = Number(newScale.toFixed(4));
			
			setScale(newScale, dispatchEvent);
				
		}
		
		/**
		 * Decreases the zoom of the target application to next value 
		 * */
		public function decreaseScale(valueFrom:Number = NaN, dispatchEvent:Boolean = true):void {
			var newScale:Number;
			var currentScale:Number;
		
			if (isNaN(valueFrom)) {
				currentScale = Number(DisplayObject(selectedDocument.instance).scaleX.toFixed(4));
			}
			else {
				currentScale = valueFrom;
			}
			
			//newScale = DisplayObject(document).scaleX;
			
			for (var i:int=scaleStops.length;i--;) {
				if (currentScale>scaleStops[i]) {
					newScale = scaleStops[i];
					break;
				}
			}
			
			if (i==0) {
				newScale = scaleStops[i];
			}
			
			newScale = Number(newScale.toFixed(4));
			
			setScale(newScale, dispatchEvent);
				
		}
		
		/**
		 * Sets the zoom of the target application to value. 
		 * */
		public function setScale(value:Number, dispatchEvent:Boolean = true):void {
			
			if (selectedDocument && !isNaN(value) && value>0) {
				//DisplayObject(selectedDocument.instance).scaleX = value;
				//DisplayObject(selectedDocument.instance).scaleY = value;
				selectedDocument.scale = value;
				
				if (dispatchEvent) {
					dispatchScaleChangeEvent(selectedDocument, value, value);
				}
			}
		}
		
		/**
		 * Gets the scale of the target application. 
		 * */
		public function getScale():Number {
			
			if (selectedDocument && selectedDocument.instance && "scaleX" in selectedDocument.instance) {
				return Math.max(selectedDocument.instance.scaleX, selectedDocument.instance.scaleY);
			}
			
			return NaN;
		}
		
		/**
		 * Center the application
		 * */
		public function centerApplication(vertically:Boolean = true, verticallyTop:Boolean = true, totalDocumentPadding:int = 0):void {
			if (!canvasScroller) return;
			var viewport:IViewport = canvasScroller.viewport;
			var documentVisualElement:IVisualElement = IVisualElement(selectedDocument.instance);
			//var contentHeight:int = viewport.contentHeight * getScale();
			//var contentWidth:int = viewport.contentWidth * getScale();
			// get document size NOT scroll content size
			var contentHeight:int = documentVisualElement.height * getScale();
			var contentWidth:int = documentVisualElement.width * getScale();
			var newHorizontalPosition:int;
			var newVerticalPosition:int;
			var needsValidating:Boolean;
			var vsbWidth:int = canvasScroller.verticalScrollBar ? canvasScroller.verticalScrollBar.width : 11;
			var hsbHeight:int = canvasScroller.horizontalScrollBar ? canvasScroller.horizontalScrollBar.height : 11;
			var availableWidth:int = canvasScroller.width;// - vsbWidth;
			var availableHeight:int = canvasScroller.height;// - hsbHeight;
			
			if (LayoutManager.getInstance().isInvalid()) {
				needsValidating = true;
				//LayoutManager.getInstance().validateClient(canvasScroller as ILayoutManagerClient);
				//LayoutManager.getInstance().validateNow();
			}
			
			
			if (vertically) {
				// scroller height 359, content height 504, content height validated 550
				// if document is taller than available space and 
				// verticalTop is true then keep it at the top
				if (contentHeight > availableHeight && verticallyTop) {
					newVerticalPosition = canvasBackground.y - totalDocumentPadding;
					viewport.verticalScrollPosition = Math.max(0, newVerticalPosition);
				}
				else if (contentHeight > availableHeight) {
					newVerticalPosition = (contentHeight + hsbHeight - availableHeight) / 2;
					viewport.verticalScrollPosition = Math.max(0, newVerticalPosition);
				}
				else {
					// content height 384, scroller height 359, vsp 12
					newVerticalPosition = (availableHeight + hsbHeight - contentHeight) / 2;
					viewport.verticalScrollPosition = Math.max(0, newVerticalPosition);
				}
			}
			
			// if width of content is wider than canvasScroller width then center
			if (canvasScroller.width < contentWidth) {
				newHorizontalPosition = (contentWidth - availableWidth) / 2;
				viewport.horizontalScrollPosition = Math.max(0, newHorizontalPosition);
			}
			else {
				//newHorizontalPosition = (contentWidth - canvasScroller.width) / 2;
				//viewport.horizontalScrollPosition = Math.max(0, newHorizontalPosition);
			}
		}
		
		/**
		 * Restores the scale of the target application to 100%.
		 * */
		public function restoreDefaultScale(dispatchEvent:Boolean = true):void {
			if (selectedDocument) {
				setScale(1, dispatchEvent);
			}
		}
		
		/**
		 * Sets the scale to fit the available space. 
		 * */
		public function scaleToFit(dispatchEvent:Boolean = true):void {
			var width:int;
			var height:int;
			var availableWidth:int;
			var availableHeight:int;
			var widthScale:Number;
			var heightScale:Number;
			var newScale:Number;
			var documentVisualElement:IVisualElement = selectedDocument ? selectedDocument.instance as IVisualElement : null;
			
			if (documentVisualElement) {
			
				//width = DisplayObject(document).width;
				//height = DisplayObject(document).height;
				width = documentVisualElement.width;
				height = documentVisualElement.height;
				var vsbWidth:int = canvasScroller.verticalScrollBar ? canvasScroller.verticalScrollBar.width : 20;
				var hsbHeight:int = canvasScroller.horizontalScrollBar ? canvasScroller.horizontalScrollBar.height : 20;
				availableWidth = canvasScroller.width - vsbWidth*2.5;
				availableHeight = canvasScroller.height - hsbHeight*2.5;
				
				//var scrollerPaddedWidth:int = canvasScroller.width + documentPadding;
				//var scrollerPaddedHeight:int = canvasScroller.height + documentPadding;
			
                // if the visible area is less than our content then scale down
                if (height > availableHeight || width > availableWidth) {
					heightScale = availableHeight/height;
					widthScale = availableWidth/width;
					newScale = Math.min(widthScale, heightScale);
					width = newScale * width;
					height = newScale * height;
                }
				else if (height < availableHeight && width < availableWidth) {
					newScale = Math.min(availableHeight/height, availableWidth/width);
					width = newScale * width;
					height = newScale * height;
					//newScale = Math.min(availableHeight/height, availableWidth/width);
					//newScale = Math.max(availableHeight/height, availableWidth/width);
                }

				setScale(newScale, dispatchEvent);
				
				////////////////////////////////////////////////////////////////////////////////
				/*var documentRatio:Number = width / height;
				var canvasRatio:Number = availableWidth / availableHeight;
				
				var newRatio:Number = documentRatio / canvasRatio;
				newRatio = canvasRatio / documentRatio;
				newRatio = 1-documentRatio / canvasRatio;*/
					
			}
		}
		
		//----------------------------------
		//
		//  Documentation Utility
		// 
		//----------------------------------
		
		public static var docsURL:String = "http://flex.apache.org/asdoc/";
		public static var docsURL2:String = "http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/";
		
		/**
		 * Returns the URL to the help document online based on MetaData passed to it. 
		 * */
		public static function getURLToHelp(metadata:MetaData, useBackupURL:Boolean = true):String {
			var path:String = "";
			var currentClass:String;
			var sameClass:Boolean;
			var prefix:String = "";
			var url:String;
			var packageName:String;
			var declaredBy:String;
			var backupURLNeeded:Boolean;
			
			if (metadata && metadata.declaredBy) {
				declaredBy = metadata.declaredBy;
				currentClass = declaredBy.replace(/::|\./g, "/");
				
				if (declaredBy.indexOf(".")!=-1) {
					packageName = declaredBy.split(".")[0];
					if (packageName=="flash") {
						backupURLNeeded = true;
					}
				}
				
				if (metadata is StyleMetaData) {
					prefix = "style:";
				}
				else if (metadata is EventMetaData) {
					prefix = "event:";
				}
				
				
				path = currentClass + ".html#" + prefix + metadata.name;
			}
			
			if (useBackupURL && backupURLNeeded) {
				url  = docsURL2 + path;
			}
			else {
				url  = docsURL + path;
			}
			
			return url;
		}
		
		//----------------------------------
		//
		//  Component Management
		// 
		//----------------------------------
		
		/**
		 * Collection of visual elements that can be added or removed to 
		 * */
		[Bindable]
		public static var componentDefinitions:ArrayCollection = new ArrayCollection();
		
		/**
		 * Cache for component icons
		 * */
		[Bindable]
		public static var contentCache:ContentCache = new ContentCache();
		
		/**
		 * Add the named component class to the list of available components
		 * */
		public static function addComponentType(name:String, className:String, classType:Object, inspectors:Array = null, icon:Object = null, defaultProperties:Object=null, defaultStyles:Object=null, enabled:Boolean = true):Boolean {
			var definition:ComponentDefinition;
			var length:uint = componentDefinitions.length;
			var item:ComponentDefinition;
			
			
			for (var i:uint;i<length;i++) {
				item = ComponentDefinition(componentDefinitions.getItemAt(i));
				
				// check if it exists already
				if (item && item.classType==classType) {
					return false;
				}
			}
			
			
			definition = new ComponentDefinition();
			
			definition.name = name;
			definition.icon = icon;
			definition.className = className;
			definition.classType = classType;
			definition.defaultStyles = defaultStyles;
			definition.defaultProperties = defaultProperties;
			definition.inspectors = inspectors;
			definition.enabled = enabled;
			
			componentDefinitions.addItem(definition);
			
			return true;
		}
		
		/**
		 * Remove the named component class
		 * */
		public static function removeComponentType(className:String):Boolean {
			var definition:ComponentDefinition;
			var length:uint = componentDefinitions.length;
			var item:ComponentDefinition;
			
			for (var i:uint;i<length;i++) {
				item = ComponentDefinition(componentDefinitions.getItemAt(i));
				
				if (item && item.classType==className) {
					componentDefinitions.removeItemAt(i);
				}
			}
			
			return true;
		}
		
		/**
		 * Get the component by class name
		 * */
		public static function getComponentType(className:String, fullyQualified:Boolean = false):ComponentDefinition {
			var definition:ComponentDefinition;
			var length:uint = componentDefinitions.length;
			var item:ComponentDefinition;
			
			for (var i:uint;i<length;i++) {
				item = ComponentDefinition(componentDefinitions.getItemAt(i));
				
				if (fullyQualified) {
					if (item && item.className==className) {
						return item;
					}
				}
				else {
					if (item && item.name==className) {
						return item;
					}
				}
			}
			
			return null;
		}
		
		/**
		 * Get the component by class name
		 * */
		public static function getDynamicComponentType(className:String, fullyQualified:Boolean = false):ComponentDefinition {
			var definition:ComponentDefinition;
			var length:uint = componentDefinitions.length;
			var item:ComponentDefinition;
			
			for (var i:uint;i<length;i++) {
				item = ComponentDefinition(componentDefinitions.getItemAt(i));
				
				if (fullyQualified) {
					if (item && item.className==className) {
						return item;
					}
				}
				else {
					if (item && item.name==className) {
						return item;
					}
				}
			}
			
			
			var hasDefinition:Boolean = ApplicationDomain.currentDomain.hasDefinition(className);
			
			
			if (hasDefinition) {
				addComponentType(className, className, null, null);
				item = getComponentType(className, fullyQualified);
				return item;
			}
			
			return null;
		}
		
		/**
		 * Removes all components. If components were removed then returns true. 
		 * */
		public static function removeAllComponents():Boolean {
			var length:uint = componentDefinitions.length;
			
			if (length) {
				componentDefinitions.removeAll();
				return true;
			}
			
			return false;
		}
		
		/**
		 * Add an asset
		 * */
		public function addAssets(data:Array, dispatchEvents:Boolean = true):void {
			var length:int;
			var added:Boolean;
			
			if (data) {
				length = data.length;
				
				for (var i:int;i<length;i++) {
					addAsset(data[i], dispatchEvents);
				}
				
			}
			
		}
		
		/**
		 * Add an asset
		 * */
		public function addAsset(data:DocumentData, dispatchEvent:Boolean = true):void {
			var length:int = assets.length;
			var found:Boolean;
			var item:DocumentData;
			
			for (var i:int;i<length;i++) {
				item = assets.getItemAt(i) as DocumentData;
				
				if (item.id==data.id && item.id!=null) {
					found = true;
					break;
				}
			}
			
			if (!found) {
				assets.addItem(data);
			}
			
			if (!found && dispatchEvent) {
				dispatchAssetAddedEvent(data);
			}
		}
		
		/**
		 * Remove an asset
		 * */
		public function removeAsset(iDocumentData:IDocumentData, locations:String = null, dispatchEvents:Boolean = true):Boolean {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var remote:Boolean = getIsRemoteLocation(locations);
			var index:int = assets.getItemIndex(iDocumentData);
			var removedInternally:Boolean;
			
			if (index!=-1) {
				assets.removeItemAt(index);
				removedInternally = true;
			}
			
			if (remote && iDocumentData && iDocumentData.id) { 
				// we need to create service
				if (deleteAttachmentService==null) {
					deleteAttachmentService = new WPService();
					deleteAttachmentService.addEventListener(WPService.RESULT, deleteDocumentResultsHandler, false, 0, true);
					deleteAttachmentService.addEventListener(WPService.FAULT, deleteDocumentFaultHandler, false, 0, true);
				}
				
				deleteAttachmentService.host = getWPURL();
				
				deleteDocumentInProgress = true;
				
				deleteAttachmentService.deleteAttachment(int(iDocumentData.id), true);
			}
			/*else if (remote) { // document not saved yet because no ID
				
				if (dispatchEvents) {
					dispatchAssetRemovedEvent(iDocumentData, removedInternally);
					return removedInternally;
				}
			}
			else {
	
				if (dispatchEvents) {
					dispatchAssetRemovedEvent(iDocumentData, removedInternally);
					return removedInternally;
				}

			}*/
			
			dispatchAssetRemovedEvent(iDocumentData, removedInternally);
			
			return removedInternally;
		}
		
		/**
		 * The canvas border.
		 * */
		public var canvasBorder:Object;
		
		/**
		 * The canvas background.
		 * */
		public var canvasBackground:Object;
		
		/**
		 * The canvas scroller.
		 * */
		public var canvasScroller:Scroller;
		
		/**
		 * Sets the canvas and canvas parent. Not sure if going to be used. 
		 * May use canvas property on document.
		 * */
		public function setCanvas(canvasBorder:Object, canvasBackground:Object, canvasScroller:Scroller, dispatchEvent:Boolean = true, cause:String = ""):void {
			//if (this.canvasBackground==canvasBackground) return;
			
			this.canvasBorder = canvasBorder;
			this.canvasBackground = canvasBackground;
			this.canvasScroller = canvasScroller;
			
			if (dispatchEvent) {
				instance.dispatchCanvasChangeEvent(canvasBackground, canvasBorder, canvasScroller);
			}
			
		}
		
		/**
		 * Sets the document
		 * */
		public function setProject(value:IProject, dispatchEvent:Boolean = true, cause:String = ""):void {
			selectedProject = value;
			/*if (_projects.length == 1 && projects==value) return;
			
			_projects = null;// without this, the contents of the array would change across all instances
			_projects = [];
			
			if (value) {
				_projects[0] = value;
			}*/
			
			if (dispatchEvent) {
				instance.dispatchProjectChangeEvent(selectedProject);
			}
			
		}
		
		/**
		 * Selects the target
		 * */
		public function setProjects(value:*, dispatchEvent:Boolean = true, cause:String = ""):void {
			value = ArrayUtil.toArray(value);
			
			// remove listeners from previous documents
			var n:int = _projects.length;
			
			for (var i:int = n - 1; i >= 0; i--) {
				if (_projects[i] == null) {
					continue;
				}
				
				//removeHandlers(_projects[i]);
			}
			
			// Strip out null values.
			// Binding will trigger again when the null projects are created.
			n = value.length;
			
			for (i = n - 1; i >= 0; i--) {
				if (value[i] == null) {
					value.splice(i,1);
					continue;
				}
				
				//addHandlers(value[i]);
			}
			
			_projects = value;
			
			if (dispatchEvent) {
				instance.dispatchProjectsSetEvent(projects);
			}
			
		}
		
		/**
		 * Sets the current document
		 * */
		public function setDocument(value:IDocument, dispatchEvent:Boolean = true, cause:String = ""):void {
			
			if (selectedDocument != value) {
				selectedDocument = value;
			}
			
			var container:IDocumentContainer = documentsContainerDictionary[value] as IDocumentContainer;
			
			if (container) {
				toolLayer = container.toolLayer;
				canvasBorder = container.canvasBorder;
				canvasBackground= container.canvasBackground;
				canvasScroller = container.canvasScroller;
			}
			
			history = selectedDocument ? selectedDocument.history : null;
			history ? history.refresh() : void;
			historyIndex = getHistoryIndex();
			
			if (dispatchEvent) {
				instance.dispatchDocumentChangeEvent(selectedDocument);
			}
			
		}
		
		/**
		 * Selects the target
		 * */
		public function setDocuments(value:*, dispatchEvent:Boolean = true, cause:String = ""):void {
			value = ArrayUtil.toArray(value);
			
			// remove listeners from previous documents
			var n:int = _documents.length;
			
			for (var i:int = n - 1; i >= 0; i--) {
				if (_documents[i] == null) {
					continue;
				}
				
				//removeHandlers(_documents[i]);
			}
			
			// Strip out null values.
			// Binding will trigger again when the null documents are created.
			n = value.length;
			
			for (i = n - 1; i >= 0; i--) {
				if (value[i] == null) {
					value.splice(i,1);
					continue;
				}
				
				//addHandlers(value[i]);
			}
			
			_documents = value;
			
			if (dispatchEvent) {
				instance.dispatchDocumentsSetEvent(documents);
			}
			
			
		}
		
		/**
		 * Selects the target
		 * */
		public function setTarget(value:*, dispatchEvent:Boolean = true, cause:String = ""):void {
			if (_targets.length == 1 && target==value) return;
			
			_targets = null;// without this, the contents of the array would change across all instances
			_targets = [];
			
			if (value) {
				_targets[0] = value;
			}
			
			if (dispatchEvent) {
				instance.dispatchTargetChangeEvent(target);
			}
			
		}
		
		/**
		 * Selects the target
		 * */
		public function setTargets(value:*, dispatchEvent:Boolean = true, cause:String = ""):void {
			value = ArrayUtil.toArray(value);
			
			// remove listeners from previous targets
			var n:int = _targets.length;
			
			for (var i:int = n - 1; i >= 0; i--) {
				if (_targets[i] == null) {
					continue;
				}
				
				//removeHandlers(_targets[i]);
			}
			
			// Strip out null values.
			// Binding will trigger again when the null targets are created.
			n = value.length;
			
			for (i = n - 1; i >= 0; i--) {
				if (value[i] == null) {
					value.splice(i,1);
					continue;
				}
				
				//addHandlers(value[i]);
			}
			
			_targets = value;
			
			
			if (dispatchEvent) {
				instance.dispatchTargetChangeEvent(_targets, true);
			}
			
		}
		
		/**
		 * Deselects the passed in targets
		 * */
		public function desetTargets(value:*, dispatchEvent:Boolean = true, cause:String = ""):void {
			value = ArrayUtil.toArray(value);
			
			throw new Error("not done");
			
			// go through current targets and remove any that match the ones in the values
			
			// remove listeners from previous targets
			var targetsLength:int = _targets.length;
			var valuesLength:int = value ? value.length : 0;
			
			for (var i:int=0;i<targetsLength;i++) {
				for (var j:int=0;j<valuesLength;j++) {
					if (value[j]==_targets[i]) {
						_targets.splice(i,1);
						continue;
					}
				}
			}
			
			
			if (dispatchEvent) {
				instance.dispatchTargetChangeEvent(_targets, true);
			}
		}
		
		/**
		 * Deselects the target
		 * */
		public function deselectedTarget(dispatchEvent:Boolean = true, cause:String = ""):void {
			
			// go through current targets and remove any that match the ones in the values
			setTarget(null, dispatchEvent, cause);
			
		}
		
		/**
		 * Deselects the target
		 * */
		public static function clearTarget(dispatchEvent:Boolean = true, cause:String = ""):void {
			setTarget(null, dispatchEvent, cause);
		}
		
		/**
		 * Selects the target
		 * */
		public static function setTarget(value:DisplayObject, dispatchEvent:Boolean = true, cause:String = ""):void {
			instance.setTarget(value, dispatchEvent, cause);
		}
		
		/**
		 * Selects the target
		 * */
		public static function setTargets(value:Object, dispatchEvent:Boolean = true, cause:String = ""):void {
			instance.setTargets(value, dispatchEvent, cause);
		}
		
		/**
		 * Selects the document
		 * */
		public static function setDocuments(value:Object, dispatchEvent:Boolean = false, cause:String = ""):void {
			instance.setDocuments(value, dispatchEvent, cause);
		}
		
		/**
		 * Deselects the documents
		 * */
		public static function desetDocuments(dispatchEvent:Boolean = true, cause:String = ""):void {
			instance.setDocuments(null, dispatchEvent, cause);
		}
		
		/**
		 * Gets the display list of the current document
		 * */
		public static function getComponentDisplayList():ComponentDescription {
			return IDocumentContainer(instance.selectedDocument).componentDescription;
		}
		
		//----------------------------------
		//  Clipboard
		//----------------------------------
		
		/**
		 * Cut item
		 * */
		public function cutItem(item:Object):void {
			//Clipboard.generalClipboard.setData(ClipboardFormats.HTML_FORMAT, );
			cutData = item;
			copiedData = null;
		}
		
		/**
		 * Copy item
		 * */
		public function copyItem(item:Object, format:String = null, handler:Function = null):void {
			//Clipboard.generalClipboard.setData(ClipboardFormats.HTML_FORMAT, );
			cutData = null;
			copiedData = item;
			
			var clipboard:Clipboard = Clipboard.generalClipboard;
			var serializable:Boolean = true;
			
			format = format ? format : "Object";
			handler = handler!=null ? handler : setClipboardDataHandler;
			
			if (true) {
				clipboard.clear();
			}
				
			try {
				
				if (item is String) {
					clipboard.setDataHandler(format, handler, serializable);
				}
				else {
					clipboard.setDataHandler(format, handler, serializable);
				}
				
				/*
				if (action.successEffect) {
					playEffect(action.successEffect);
				}
				
				if (action.hasEventListener(CopyToClipboard.SUCCESS)) {
					dispatchActionEvent(new Event(CopyToClipboard.SUCCESS));
				}*/
			}
			catch (error:ErrorEvent) {
				
				/*
				if (action.errorEffect) {
					playEffect(action.errorEffect);
				}
				
				if (action.hasEventListener(CopyToClipboard.ERROR)) {
					dispatchActionEvent(new Event(CopyToClipboard.ERROR));
				}*/
			}
		}
		
		/**
		 * Set clipboard data handler
		 * */
		public function setClipboardDataHandler():* {
			/*Format	Return Type
			ClipboardFormats.TEXT_FORMAT	String
			ClipboardFormats.HTML_FORMAT	String
			ClipboardFormats.URL_FORMAT	String (AIR only)
			ClipboardFormats.RICH_TEXT_FORMAT	ByteArray
			ClipboardFormats.BITMAP_FORMAT	BitmapData (AIR only)
			ClipboardFormats.FILE_LIST_FORMAT	Array of File (AIR only)
			ClipboardFormats.FILE_PROMISE_LIST_FORMAT	Array of File (AIR only)
			Custom format name	Non-void*/
			
			
			
			if (copiedData) {
				return copiedData;
			}
			else if (cutData) {
				return cutData;
			}
			
			//Clipboard.generalClipboard.setData(ClipboardFormats.HTML_FORMAT, );
		}
		
		/**
		 * Copy item
		 * */
		public function pasteItem(destination:Object):void {
			//Clipboard.generalClipboard.setData(ClipboardFormats.HTML_FORMAT, );
		}
		
		/**
		 * Set attributes on a component object
		 * */
		public static function setAttributesOnComponent(elementInstance:Object, node:XML, dispatchEvents:Boolean = false):void {
			var attributeName:String;
			var elementName:String = node.localName();
			//var domain:ApplicationDomain = ApplicationDomain.currentDomain;
			//var componentDefinition:ComponentDefinition = Radiate.getComponentType(elementName);
			//var className:String =componentDefinition ? componentDefinition.className :null;
			//var classType:Class = componentDefinition ? componentDefinition.classType as Class :null;
			//var elementInstance:Object = componentDescription.instance;
			
			
			for each (var attribute:XML in node.attributes()) {
				attributeName = attribute.name().toString();
				//Radiate.log.info(" found attribute: " + attributeName); 
				
				
				// TODO we should check if an attribute is an property, style or event using the component definition
				// We can do it this way now since we are only working with styles and properties
				
				
				// check if property 
				if (attributeName in elementInstance) {
					
					//Radiate.log.info(" setting property: " + attributeName);
					setProperty(elementInstance, attributeName, attribute.toString(), null, false, dispatchEvents);
				 	
				}
				
				// could be style or event
				else {
					if (elementInstance is IStyleClient) {
						//Radiate.log.info(" setting style: " + attributeName);
						setStyle(elementInstance, attributeName, attribute.toString(), null, false, dispatchEvents);
					}
				}
			}
		}
		
		/**
		 * Returns true if the property was changed. Use setProperties for 
		 * setting multiple properties.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.setProperty(myButton, "x", 40);</pre>
		 * <pre>Radiate.setProperty([myButton,myButton2], "x", 40);</pre>
		 * */
		public static function clearStyle(target:Object, style:String, description:String = null):Boolean {
			
			return setStyle(target, style, undefined, description, true);
		}
		
		/**
		 * Returns true if the property was changed. Use setProperties for 
		 * setting multiple properties.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.setProperty(myButton, "x", 40);</pre>
		 * <pre>Radiate.setProperty([myButton,myButton2], "x", 40);</pre>
		 * */
		public static function setStyle(target:Object, style:String, value:*, description:String = null, keepUndefinedValues:Boolean = false, dispatchEvents:Boolean = true):Boolean {
			var targets:Array = ArrayUtil.toArray(target);
			var styleChanges:Array;
			var historyEvents:Array;
			
			styleChanges = createPropertyChange(targets, null, style, value, description);
			
			
			if (!keepUndefinedValues) {
				styleChanges = stripUnchangedValues(styleChanges);
			}
			
			if (changesAvailable(styleChanges)) {
				applyChanges(targets, styleChanges, null, style);
				//LayoutManager.getInstance().validateNow(); // applyChanges calls this
				
				historyEvents = createHistoryEvents(targets, styleChanges, null, style, value);
				
				updateComponentStyles(targets, styleChanges);
				
				addHistoryEvents(historyEvents, description);
				
				if (dispatchEvents) {
					instance.dispatchPropertyChangeEvent(targets, styleChanges, ArrayUtil.toArray(style));
				}
				return true;
			}
			
			return false;
		}
		
		/**
		 * Returns true if the property was changed. Use setProperties for 
		 * setting multiple properties.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.setProperty(myButton, "x", 40);</pre>
		 * <pre>Radiate.setProperty([myButton,myButton2], "x", 40);</pre>
		 * */
		public static function setProperty(target:Object, property:String, value:*, description:String = null, keepUndefinedValues:Boolean = false, dispatchEvents:Boolean = true):Boolean {
			var targets:Array = ArrayUtil.toArray(target);
			var propertyChanges:Array;
			var historyEvents:Array;
			
			propertyChanges = createPropertyChange(targets, property, null, value, description);
			
			
			if (!keepUndefinedValues) {
				propertyChanges = stripUnchangedValues(propertyChanges);
			}
			
			if (changesAvailable(propertyChanges)) {
				applyChanges(targets, propertyChanges, property, null);
				//LayoutManager.getInstance().validateNow(); // applyChanges calls this
				//addHistoryItem(propertyChanges, description);
				
				historyEvents = createHistoryEvents(targets, propertyChanges, property, null, value);
				
				addHistoryEvents(historyEvents, description);
				
				updateComponentProperties(targets, propertyChanges);
				
				if (dispatchEvents) {
					instance.dispatchPropertyChangeEvent(targets, propertyChanges, ArrayUtil.toArray(property));
				}
				
				if (dispatchEvents) {
					if (targets.indexOf(instance.selectedDocument.instance)!=-1 && ArrayUtils.containsAny(notableApplicationProperties, [property])) {
						instance.dispatchDocumentSizeChangeEvent(targets);
					}
				}
				
				return true;
			}
			
			return false;
		}
		
		/**
		 * Properties on the application to listen for for document size change event
		 * */
		public static var notableApplicationProperties:Array = ["width","height","scaleX","scaleY"];
		
		/**
		 * Returns true if the property(s) were changed.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>setProperties([myButton,myButton2], ["x","y"], {x:40,y:50});</pre>
		 * <pre>setProperties(myButton, "x", 40);</pre>
		 * <pre>setProperties(button, ["x", "left"], {x:50,left:undefined});</pre>
		 * 
		 * @see setStyle()
		 * @see setStyles()
		 * @see setProperty()
		 * */
		public static function setProperties(target:Object, properties:Array, value:*, description:String = null, keepUndefinedValues:Boolean = false):Boolean {
			var propertyChanges:Array;
			var historyEvents:Array;
			var targets:Array;
			
			targets = ArrayUtil.toArray(target);
			properties = ArrayUtil.toArray(properties);
			propertyChanges = createPropertyChanges(targets, properties, null, value, description, false);
			
			if (!keepUndefinedValues) {
				propertyChanges = stripUnchangedValues(propertyChanges);
			}
			
			if (changesAvailable(propertyChanges)) {
				applyChanges(targets, propertyChanges, properties, null);
				//LayoutManager.getInstance().validateNow();
				//addHistoryItem(propertyChanges);
				
				historyEvents = createHistoryEvents(targets, propertyChanges, properties, null, value);
				
				addHistoryEvents(historyEvents, description);
				
				updateComponentProperties(targets, propertyChanges);
				
				instance.dispatchPropertyChangeEvent(targets, propertyChanges, properties);
				
				if (targets.indexOf(instance.selectedDocument)!=-1 && ArrayUtils.containsAny(notableApplicationProperties, properties)) {
					instance.dispatchDocumentSizeChangeEvent(targets);
				}
				return true;
			}
			
			return false;
		}
		
		/**
		 * Returns true if the property(s) were changed.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>setProperties([myButton,myButton2], ["x","y"], {x:40,y:50});</pre>
		 * <pre>setProperties(myButton, "x", 40);</pre>
		 * <pre>setProperties(button, ["x", "left"], {x:50,left:undefined});</pre>
		 * 
		 * @see setStyle()
		 * @see setProperty()
		 * @see setProperties()
		 * */
		public static function setStyles(target:Object, styles:Array, value:*, description:String = null, keepUndefinedValues:Boolean = false):Boolean {
			var stylesChanges:Array;
			var historyEvents:Array;
			var targets:Array;
			
			targets = ArrayUtil.toArray(target);
			styles = ArrayUtil.toArray(styles);
			stylesChanges = createPropertyChanges(targets, styles, null, value, description, false);
			
			if (!keepUndefinedValues) {
				stylesChanges = stripUnchangedValues(stylesChanges);
			}
			
			if (changesAvailable(stylesChanges)) {
				applyChanges(targets, stylesChanges, null, styles);
				//LayoutManager.getInstance().validateNow();
				
				historyEvents = createHistoryEvents(targets, stylesChanges, null, styles, value);
				
				addHistoryEvents(historyEvents, description);
				
				updateComponentStyles(targets, stylesChanges);
				
				instance.dispatchPropertyChangeEvent(targets, stylesChanges, styles);
				return true;
			}
			
			return false;
		}
		
		/**
		 * Updates the properties on a component description
		 * */
		public static function updateComponentProperties(targets:Array, propertyChanges:Array):void {
			var descriptor:ComponentDescription;
			var targetLength:int = targets.length;
			var changesLength:int = propertyChanges.length;
			var propertyChange:Object;
			var target:Object;
			
			for (var i:int;i<targetLength;i++) {
				target = targets[i];
				descriptor = instance.selectedDocument.descriptionsDictionary[target];
				
				for (var j:int=0;j<changesLength;j++) {
					propertyChange = propertyChanges[j];
					
					if (descriptor) {
						descriptor.properties = ObjectUtils.merge(propertyChange.end, descriptor.properties);
					}
				}
				
			}
		}
		
		/**
		 * Updates the styles on a component description
		 * */
		public static function updateComponentStyles(targets:Array, propertyChanges:Array):void {
			var descriptor:ComponentDescription;
			var targetLength:int = targets.length;
			var changesLength:int = propertyChanges.length;
			var propertyChange:Object;
			var target:Object;
			
			for (var i:int;i<targetLength;i++) {
				target = targets[i];
				descriptor = instance.selectedDocument.descriptionsDictionary[target];
				
				for (var j:int=0;j<changesLength;j++) {
					propertyChange = propertyChanges[j];
					
					if (descriptor) {
						descriptor.styles = ObjectUtils.merge(propertyChange.end, descriptor.styles);
					}
				}
				
				// remove nulls and undefined values
				
			}
		}
		
		/**
		 * Gets the value translated into a type. 
		 * */
		public static function getTypedValue(value:*, valueType:*):* {
			
			return TypeUtils.getTypedValue(value, valueType);
		}
		
		
		/**
		 * Move a component in the display list and sets any properties 
		 * such as positioning<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.moveElement(new Button(), parentComponent, [], null);</pre>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.moveElement(radiate.target, null, ["x"], 15);</pre>
		 * */
		public static function moveElement(items:*, 
										   destination:Object, 
										   properties:Array, 
										   styles:Array,
										   values:Object, 
										   description:String 	= RadiateEvent.MOVE_ITEM, 
										   position:String		= AddItems.LAST, 
										   relativeTo:Object	= null, 
										   index:int			= -1, 
										   propertyName:String	= null, 
										   isArray:Boolean		= false, 
										   isStyle:Boolean		= false, 
										   vectorClass:Class	= null,
										   keepUndefinedValues:Boolean = true):String {
			
			var visualElement:IVisualElement;
			var moveItems:AddItems;
			var childIndex:int;
			var propertyChangeChange:PropertyChanges;
			var changes:Array;
			var historyEvents:Array;
			var isSameOwner:Boolean;
			var isSameParent:Boolean;
			var removeBeforeAdding:Boolean;
			var currentIndex:int;
			var movingIndexWithinParent:Boolean;
			
			items = ArrayUtil.toArray(items);
			
			var item:Object = items ? items[0] : null;
			var itemOwner:Object = item ? item.owner : null;
			
			visualElement = item as IVisualElement;
			var visualElementParent:Object = visualElement ? visualElement.parent : null;
			var visualElementOwner:IVisualElementContainer = itemOwner as IVisualElementContainer;
			var applicationGroup:GroupBase = destination is Application ? Application(destination).contentGroup : null;
			
			isSameParent = visualElementParent && (visualElementParent==destination || visualElementParent==applicationGroup);
			isSameOwner = visualElementOwner && visualElementOwner==destination;
			
			// set default description
			if (!description) {
				description = ADD_ITEM_DESCRIPTION;
			}
			
			// if it's a basic layout then don't try to add it
			// NO DO ADD IT bc we may need to swap indexes
			if (destination is IVisualElementContainer) {
				//destinationGroup = destination as GroupBase;
				
				if (destination.layout is BasicLayout) {
					
					// does not support multiple items?
					// check if group parent and destination are the same
					if (item && itemOwner==destination) {
						//trace("can't add to the same owner in a basic layout");
						isSameOwner = true;
						
						//return SAME_OWNER;
					}
					
					// check if group parent and destination are the same
					// NOTE: if the item is an element on application this will fail
					if (item && visualElementParent && (visualElementParent==destination || visualElementParent==applicationGroup)) {
						//trace("can't add to the same parent in a basic layout");
						isSameParent = true;
						//return SAME_PARENT;
					}
				}
				// if element is already child of layout container and there is only one element 
				else if (items && destination is IVisualElementContainer 
						&& destination.numElements==1
						&& visualElementParent
						&& (visualElementParent==destination || visualElementParent==applicationGroup)) {
					
					isSameParent = true;
					isSameOwner = true;
					//trace("can't add to the same parent in a basic layout");
					//return SAME_PARENT;
					
				}
			}
			
			// if destination is null then we assume we are moving
			// WRONG! null should mean remove
			else {
				//isSameParent = true;
				//isSameOwner = true;
			}
			
			
			// set default
			if (!position) {
				position = AddItems.LAST;
			}
			
			// if destination is not a basic layout Group and the index is set 
			// then find and override position and set the relative object 
			// so we can position the target in the drop location point index
			if (destination is IVisualElementContainer 
				&& !relativeTo 
				&& index!=-1
				&& destination.numElements>0) {
				
				// add as first item
				if (index==0) {
					position = AddItems.FIRST;
				}
					
					// get relative to object
				else if (index<=destination.numElements) {
					visualElement = items is Array && (items as Array).length>0 ? items[0] as IVisualElement : items as IVisualElement;
					
					// if element is already child of container account for removal of element before add
					if (visualElement && visualElement.parent == destination) {
						childIndex = destination.getElementIndex(visualElement);
						index = childIndex < index ? index-1: index;
						
						if (index<=0) {
							position = AddItems.FIRST;
						}
						else {
							relativeTo = destination.getElementAt(index-1);
							position = AddItems.AFTER;
						}
					}
						// add as last item
					else if (index>=destination.numElements) {
						
						// we need to remove first or we get an error in AddItems
						// or we can set relativeTo item and set AFTER
						if (isSameParent && destination.numElements>1) {
							removeBeforeAdding = true;
							relativeTo = destination.getElementAt(destination.numElements-1);
							position = AddItems.AFTER;
						}
						else if (isSameParent) {
							removeBeforeAdding = true;
							position = AddItems.LAST;
						}
						else {
							position = AddItems.LAST;
						}
					}
						// add after first item
					else if (index>0) {
						relativeTo = destination.getElementAt(index-1);
						position = AddItems.AFTER;
					}
				}
				
				
				// check if moving to another index within the same parent 
				if (visualElementOwner && visualElement) {
					currentIndex = visualElementOwner.getElementIndex(visualElement);
					
					if (currentIndex!=index) {
						movingIndexWithinParent = true;
					}
				}
			}
			
			
			// create a new AddItems instance and add it to the changes
			moveItems = new AddItems();
			moveItems.items = items;
			moveItems.destination = destination;
			moveItems.position = position;
			moveItems.relativeTo = relativeTo;
			moveItems.propertyName = propertyName;
			moveItems.isArray = isArray;
			moveItems.isStyle = isStyle;
			moveItems.vectorClass = vectorClass;
			
			// add properties that need to be modified
			if (properties && properties.length>0 ||
				styles && styles.length>0) {
				changes = createPropertyChanges(items, properties, styles, values, description, false);
				
				// get the property change part
				propertyChangeChange = changes[0];
			}
			else {
				changes = [];
			}
			
			// constraints use undefined values 
			// so if we use constraints do not strip out values
			if (!keepUndefinedValues) {
				changes = stripUnchangedValues(changes);
			}
			
			
			// attempt to add or move and set the properties
			try {
				
				// insert moving of items before it
				// if it's the same owner we don't want to run add items 
				// but if it's a vgroup or hgroup does this count
				if ((!isSameParent && !isSameOwner) || movingIndexWithinParent) {
					changes.unshift(moveItems); //add before other changes 
				}
				
				if (changes.length==0) {
					Radiate.log.info("Move: Nothing to change or add");
					return "Nothing to change or add";
				}
				
				// store changes
				historyEvents = createHistoryEvents(items, changes, properties, styles, values, description, RadiateEvent.MOVE_ITEM);
				
				// try moving
				if ((!isSameParent && !isSameOwner) || movingIndexWithinParent) {
					
					// this is to prevent error in AddItem when adding to the last position
					// and we get an index is out of range. 
					// 
					// for example, if an element is at index 0 and there are 3 elements 
					// then addItem will get the last index. 
					// but since the parent is the same the addElement call removes 
					// the element. the max index is reduced by one and previously 
					// determined last index is now out of range. 
					// AddItems was not meant to add an element that has already been added
					// so we remove it before hand so addItems can add it again. 
					if (removeBeforeAdding) {
						visualElementOwner.removeElement(visualElement);
					}
					
					moveItems.apply(moveItems.destination as UIComponent);
					
					if (moveItems.destination is SkinnableContainer && !SkinnableContainer(moveItems.destination).deferredContentCreated) {
						//Radiate.log.error("Not added because deferred content not created.");
						var factory:DeferredInstanceFromFunction = new DeferredInstanceFromFunction(deferredInstanceFromFunction);
						SkinnableContainer(moveItems.destination).mxmlContentFactory = factory;
						SkinnableContainer(moveItems.destination).createDeferredContent();
						SkinnableContainer(moveItems.destination).removeAllElements();
						moveItems.apply(moveItems.destination as UIComponent);
					}
					
					LayoutManager.getInstance().validateNow();
				}
				
				// try setting properties
				if (changesAvailable([propertyChangeChange])) {
					applyChanges(items, [propertyChangeChange], properties, styles);
					LayoutManager.getInstance().validateNow();
				}
				
				// add to history
				addHistoryEvents(historyEvents);
				
				// check for changes before dispatching
				if (changes.indexOf(moveItems)!=-1) {
					instance.dispatchMoveEvent(items, changes, properties);
				}
				
				setTargets(items, true);
				
				if (properties) {
					instance.dispatchPropertyChangeEvent(items, changes, properties);
				}
				
				return MOVED; // we assume moved if it got this far - needs more checking
			}
			catch (error:Error) {
				// this is clunky - needs to be upgraded
				Radiate.log.error("Move error: " + error.message);
				removeHistoryEvent(changes);
				removeHistoryItem(changes);
				return String(error.message);
			}
			
			
			return ADD_ERROR;
			
		}
			
		/**
		 * Adds a component to the display list.
		 * It should not have a parent or owner! If it does
		 * it will return an error message
		 * Returns true if the component was added
		 * 
		 * Usage:
		 * Radiate.addElement(new Button(), event.targetCandidate);
		 * */
		public static function addElement(items:*, 
										  destination:Object, 
										  properties:Array 		= null, 
										  styles:Array			= null,
										  values:Object			= null, 
										  description:String 	= RadiateEvent.ADD_ITEM, 
										  position:String		= AddItems.LAST, 
										  relativeTo:Object		= null, 
										  index:int				= -1, 
										  propertyName:String	= null, 
										  isArray:Boolean		= false, 
										  isStyle:Boolean		= false, 
										  vectorClass:Class		= null,
										  keepUndefinedValues:Boolean = true):String {
			
			var results:String = moveElement(items, destination, properties, styles, values, 
								description, position, relativeTo, index, propertyName, 
								isArray, isStyle, vectorClass, keepUndefinedValues);
			
			var component:Object = ArrayUtil.toArray(items)[0];
		
			// if text based or combo box we need to prevent 
			// interaction with cursor
			if (component is TextBase || component is SkinnableTextBase) {
				component.mouseChildren = false;
				
				if ("textDisplay" in component && component.textDisplay) {
					component.textDisplay.enabled = false;
				}
			}
			
			if (component is ComboBox) {
				if ("textInput" in component && component.textInput.textDisplay) {
					component.textInput.textDisplay.enabled = false;
				}
			}
			
			// we can't add elements if skinnablecontainer._deferredContentCreated is false
			if (component is BorderContainer) {
				/*var factory:DeferredInstanceFromFunction;
				factory = new DeferredInstanceFromFunction(deferredInstanceFromFunction);
				BorderContainer(component).mxmlContentFactory = factory;
				BorderContainer(component).createDeferredContent();
				BorderContainer(component).removeAllElements();*/
				
				// we could probably also do this: 
				BorderContainer(component).addElement(new Label());
				BorderContainer(component).removeAllElements();
				
			}
			
			// we need a custom FlexSprite class to do this
			// do this after drop
			if ("eventListeners" in component && !(component is GroupBase)) {
				component.removeAllEventListeners();
			}
			
			return results;
		}
		
		
		/**
		 * Removes an element from the display list.<br/><br/>
		 * 
		 * Usage:<br/>
		 * <pre>Radiate.removeElement(radiate.targets);</pre>
		 * */
		public static function removeElement(items:*, description:String = RadiateEvent.REMOVE_ITEM):String {
			
			var visualElement:IVisualElement;
			var removeItems:AddItems;
			var childIndex:int;
			var propertyChangeChange:PropertyChanges;
			var changes:Array;
			var historyEvents:Array;
			var isSameOwner:Boolean;
			var isSameParent:Boolean;
			var removeBeforeAdding:Boolean;
			var currentIndex:int;
			var movingIndexWithinParent:Boolean;
			
			items = ArrayUtil.toArray(items);
			
			var item:Object = items ? items[0] : null;
			var itemOwner:Object = item ? item.owner : null;
			
			visualElement = item as IVisualElement;
			var visualElementParent:Object = visualElement ? visualElement.parent : null;
			var visualElementOwner:IVisualElementContainer = itemOwner as IVisualElementContainer;
			var applicationGroup:GroupBase = destination is Application ? Application(destination).contentGroup : null;
			
			isSameParent = visualElementParent && (visualElementParent==destination || visualElementParent==applicationGroup);
			isSameOwner = visualElementOwner && visualElementOwner==destination;
			
			// set default description
			if (!description) {
				description = REMOVE_ITEM_DESCRIPTION;
			}
			/*
			// if it's a basic layout then don't try to add it
			// NO DO ADD IT bc we may need to swap indexes
			if (destination is IVisualElementContainer) {
				//destinationGroup = destination as GroupBase;
				
				if (destination.layout is BasicLayout) {
					
					// does not support multiple items?
					// check if group parent and destination are the same
					if (item && itemOwner==destination) {
						//trace("can't add to the same owner in a basic layout");
						isSameOwner = true;
						
						//return SAME_OWNER;
					}
					
					// check if group parent and destination are the same
					// NOTE: if the item is an element on application this will fail
					if (item && visualElementParent && (visualElementParent==destination || visualElementParent==applicationGroup)) {
						//trace("can't add to the same parent in a basic layout");
						isSameParent = true;
						//return SAME_PARENT;
					}
				}
				// if element is already child of layout container and there is only one element 
				else if (items && destination is IVisualElementContainer 
						&& destination.numElements==1
						&& visualElementParent
						&& (visualElementParent==destination || visualElementParent==applicationGroup)) {
					
					isSameParent = true;
					isSameOwner = true;
					//trace("can't add to the same parent in a basic layout");
					//return SAME_PARENT;
					
				}
			}
			
			// if destination is null then we assume we are moving
			// WRONG! null should mean remove
			else {
				//isSameParent = true;
				//isSameOwner = true;
			}*/
			
			
			// set default
			/*if (!position) {
				position = AddItems.LAST;
			}*/
			
			// if destination is not a basic layout Group and the index is set 
			// then find and override position and set the relative object 
			// so we can position the target in the drop location point index
			/*if (destination is IVisualElementContainer 
				&& !relativeTo 
				&& index!=-1
				&& destination.numElements>0) {
				
				// add as first item
				if (index==0) {
					position = AddItems.FIRST;
				}
					
					// get relative to object
				else if (index<=destination.numElements) {
					visualElement = items is Array && (items as Array).length>0 ? items[0] as IVisualElement : items as IVisualElement;
					
					// if element is already child of container account for removal of element before add
					if (visualElement && visualElement.parent == destination) {
						childIndex = destination.getElementIndex(visualElement);
						index = childIndex < index ? index-1: index;
						
						if (index<=0) {
							position = AddItems.FIRST;
						}
						else {
							relativeTo = destination.getElementAt(index-1);
							position = AddItems.AFTER;
						}
					}
						// add as last item
					else if (index>=destination.numElements) {
						
						// we need to remove first or we get an error in AddItems
						// or we can set relativeTo item and set AFTER
						if (isSameParent && destination.numElements>1) {
							removeBeforeAdding = true;
							relativeTo = destination.getElementAt(destination.numElements-1);
							position = AddItems.AFTER;
						}
						else if (isSameParent) {
							removeBeforeAdding = true;
							position = AddItems.LAST;
						}
						else {
							position = AddItems.LAST;
						}
					}
						// add after first item
					else if (index>0) {
						relativeTo = destination.getElementAt(index-1);
						position = AddItems.AFTER;
					}
				}
				
				
				// check if moving to another index within the same parent 
				if (visualElementOwner && visualElement) {
					currentIndex = visualElementOwner.getElementIndex(visualElement);
					
					if (currentIndex!=index) {
						movingIndexWithinParent = true;
					}
				}
			}*/
			
			if (visualElement is Application) {
				log.info("You can't remove the design view");
				return REMOVE_ERROR;
			}
			
			var destination:Object = item.owner;
			var index:int = destination.getElementIndex(visualElement);
			var position:String;
			
			// create a new AddItems instance and add it to the changes
			//moveItems = new AddItems();
			//moveItems.items = items;
			//moveItems.destination = destination;
			//moveItems.position = position;
			//moveItems.relativeTo = relativeTo;
			//moveItems.propertyName = propertyName;
			//moveItems.isArray = isArray;
			//moveItems.isStyle = isStyle;
			//moveItems.vectorClass = vectorClass;
			
			changes = [];
			
			
			// attempt to remove
			try {
				removeItems = createReverseAddItems(items[0]);
				changes.unshift(removeItems);
				
				// store changes
				historyEvents = createHistoryEvents(items, changes, null, null, null, description, RadiateEvent.REMOVE_ITEM);
				
				// try moving
				//removeItems.apply(destination as UIComponent);
				//removeItems.apply(null);
				visualElementOwner.removeElement(visualElement);
				//removeItems.remove(destination as UIComponent);
				LayoutManager.getInstance().validateNow();
				
				
				// add to history
				addHistoryEvents(historyEvents);
				
				// check for changes before dispatching
				instance.dispatchRemoveItemsEvent(items, changes, null);
				// select application - could be causing errors - should select previous targets??
				setTargets(instance.selectedDocument.instance, true);
				
				return REMOVED; // we assume moved if it got this far - needs more checking
			}
			catch (error:Error) {
				// this is clunky - needs to be upgraded
				Radiate.log.error("Remove error: " + error.message);
				removeHistoryEvent(changes);
				removeHistoryItem(changes);
				return String(error.message);
			}
			
			return REMOVE_ERROR;
		}
		
		/**
		 * Required for creating BorderContainers
		 * */
		protected static function deferredInstanceFromFunction():Array {
			var label:Label = new Label();
			return [label];
		}
		
		/**
		 * Creates an instance of the component in the descriptor and sets the 
		 * default properties. We may need to use setActualSize type of methods here or when added. 
		 * */
		public static function createComponentForAdd(iDocument:IDocument, item:ComponentDefinition, setDefaults:Boolean = true):Object {
			var classFactory:ClassFactory;
			var component:Object;
			var componentDescription:ComponentDescription = new ComponentDescription();
			
			// Create component to drag
			classFactory = new ClassFactory(item.classType as Class);
			
			if (setDefaults) {
				classFactory.properties = item.defaultProperties;
				componentDescription.properties = item.defaultProperties;
				componentDescription.defaultProperties = item.defaultProperties;
			}
			
			component = classFactory.newInstance();
			
			for (var property:String in item.defaultProperties) {
				setProperty(component, property, [item.defaultProperties[property]]);
			}
			
			componentDescription.instance = component;
			componentDescription.name = item.name;
			
			iDocument.descriptionsDictionary[component] = componentDescription;
			
			if (component is Label) {
				
			}
			
			// working on grid
			if (component is spark.components.Grid) {
				spark.components.Grid(component).itemRenderer= new ClassFactory(DefaultGridItemRenderer);
				spark.components.Grid(component).dataProvider = new ArrayCollection(["item 1", "item 2", "item 3"]);
			}
			
			// working on mx grid
			if (component is mx.containers.Grid) {
				mx.containers.Grid(component)
				var grid:mx.containers.Grid = component as mx.containers.Grid;
				var gridRow:GridRow	= new GridRow();
				var gridItem:GridItem = new GridItem();
				var gridItem2:GridItem = new GridItem();
				
				var gridButton:Button = new Button();
				gridButton.width = 100;
				gridButton.height = 100;
				gridButton.label = "hello";
				var gridButton2:Button = new Button();
				gridButton2.width = 100;
				gridButton2.height = 100;
				gridButton2.label = "hello2";
				
				gridItem.addElement(gridButton);
				gridItem2.addElement(gridButton2);
				gridRow.addElement(gridItem);
				gridRow.addElement(gridItem2);
				grid.addElement(gridRow);
			}
			
			// add fill to rect
			if (component is Rect) {
				var fill:SolidColor = new SolidColor();
				fill.color = 0xf6f6f6;
				Rect(component).fill = fill;
			}
			
			// we need a custom FlexSprite class to do this
			// do this after drop
			/*if ("eventListeners" in component) {
				component.removeAllEventListeners();
			}*/
			
			// if text based or combo box we need to prevent 
			// interaction with cursor
			if (component is TextBase || component is SkinnableTextBase) {
				component.mouseChildren = false;
				
				if ("textDisplay" in component && component.textDisplay) {
					component.textDisplay.enabled = false;
				}
			}
			
			if (component is LinkButton) {
				LinkButton(component).useHandCursor = false;
			}
			/*
			if (component is IFlexDisplayObject) {
				//component.width = IFlexDisplayObject(component).measuredWidth;
				//component.height = IFlexDisplayObject(component).measuredHeight;
			}*/
			
			if (component is GroupBase) {
				DisplayObjectUtils.addGroupMouseSupport(component as GroupBase);
			}
			
			// we can't add elements if skinnablecontainer._deferredContentCreated is false
			/*if (component is BorderContainer) {
				BorderContainer(component).creationPolicy = ContainerCreationPolicy.ALL;
				BorderContainer(component).initialize();
				BorderContainer(component).createDeferredContent();
				BorderContainer(component).initialize();
			}*/
			
			return component;
		}
		
		/**
		 * Exports an XML string for a project
		 * */
		public function exportProject(project:IProject, format:String = "String"):String {
			var projectString:String = project.toString();
			
			return projectString;
		}
		
		/**
		 * Creates a project
		 * */
		public function createProject(name:String = null):IProject {
			var newProject:IProject = new Project();
			
			newProject.name = name ? name : "Project "  + Project.nameIndex;
			newProject.host = getWPURL();
			
			return newProject;
		}
		
		
		// Error #1047: Parameter initializer unknown or is not a compile-time constant.
		// Occassionally a 1047 error shows up. 
		// This is from using a static var in the parameter as the default 
		// and is an error in FB - run clean and it will go away
		
		/**
		 * Adds a project to the projects array. We should remove open project behavior. 
		 * */
		public function addProject(newProject:IProject, open:Boolean = false, locations:String = null, dispatchEvents:Boolean = true):IProject {
			var found:Boolean = doesProjectExist(newProject.uid);
			
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			
			if (!found) {
				projects.push(newProject);
			}
			else {
				return newProject;
			}
			
			// if no projects exist select the first one
			/*if (!selectedProject) {
				setProject(newProject, dispatchEvents);
			}*/
			
			if (dispatchEvents) {
				dispatchProjectAddedEvent(newProject);
			}

			if (open) {
				openProject(newProject, locations, dispatchEvents);// TODO project opened or changed
			}

			return newProject;
		}
		
		/**
		 * Opens the project. Right now this does not do much. 
		 * */
		public function openProject(iProject:IProject, locations:String = null, dispatchEvents:Boolean = true):Object {
			var isAlreadyOpen:Boolean;
			
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			
			isAlreadyOpen = isProjectOpen(iProject);
			
			/*
			if (dispatchEvents) {
				dispatchProjectChangeEvent(iProject);
			}*/
			
			if (iProject as EventDispatcher) {
				EventDispatcher(iProject).addEventListener(Project.PROJECT_OPENED, projectOpenResultHandler, false, 0, true);
			}
			
			// TODO open project documents
			iProject.open(locations);
			
			if (isAlreadyOpen) {
				//setProject(iProject, dispatchEvents);
				return true;
			}
			else {
				iProject.isOpen = true;
			}
			
			
			// show project
			//setProject(iProject, dispatchEvents);
			
			return true;
		}
		
		/**
		 * Project opened result handler
		 * */
		public function projectOpenResultHandler(event:Event):void {
			var iProject:IProject = event.currentTarget as IProject;
			
			// add assets
			addAssets(iProject.assets);
			
			if (iProject is EventDispatcher) {
				EventDispatcher(iProject).removeEventListener(Project.PROJECT_OPENED, projectOpenResultHandler);
			}
			
			dispatchProjectOpenedEvent(iProject);
		}
		
		/**
		 * Opens the project. Right now this does not do much. 
		 * */
		public function openProjectFromMetaData(iProject:IProject, locations:String = null, dispatchEvents:Boolean = true):Object {
			var isAlreadyOpen:Boolean;
			
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			
			isAlreadyOpen = isProjectOpen(iProject);
			
			/*
			if (dispatchEvents) {
				dispatchProjectChangeEvent(iProject);
			}*/
			
			if (iProject as EventDispatcher) {
				EventDispatcher(iProject).addEventListener(Project.PROJECT_OPENED, projectOpenResultHandler, false, 0, true);
			}
			
			// TODO open project documents
			iProject.openFromMetaData(locations);
			
			if (isAlreadyOpen) {
				//setProject(iProject, dispatchEvents);
				return true;
			}
			else {
				iProject.isOpen = true;
			}
			
			
			// show project
			//setProject(iProject, dispatchEvents);
			
			return true;
		}
		
		/**
		 * Checks if project is open.
		 * */
		public function isProjectOpen(iProject:IProject):Boolean {
			
			return iProject.isOpen;
		}
		
		/**
		 * Closes project if open.
		 * */
		public function closeProject(iProject:IProject, dispatchEvents:Boolean = true):Boolean {
			var length:int = iProject.documents.length;
			log.info("Close project");
			if (dispatchEvents) {
				dispatchProjectClosingEvent(iProject);
			}
			
			for (var i:int=length;i--;) {
				closeDocument(IDocument(iProject.documents[i]));
				//removeDocument(IDocument(iProject.documents[i]));
			}
			
			iProject.close();
			
			if (dispatchEvents) {
				dispatchProjectClosedEvent(iProject);
			}
			
			return false;			
		}
		
		/**
		 * Removes a project from the projects array. TODO Remove from server
		 * */
		public function removeProject(iProject:IProject, locations:String = null, dispatchEvents:Boolean = true):Boolean {
			// 1047: Parameter initializer unknown or is not a compile-time constant.
			// Occassionally a 1047 error shows up. 
			// This is from using a static var in the parameter as the default 
			// and is an error in FB - run clean and it will go away
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			
			var projectIndex:int = projects.indexOf(iProject);
			var removedProject:IProject;
			var remote:Boolean = getIsRemoteLocation(locations);
			
			if (projectIndex!=-1) {
				var removedProjects:Array = projects.splice(projectIndex, 1);
				
				if (removedProjects[0]==iProject) {
					log.info("Project removed successfully");
					
					var length:int = iProject.documents.length;
					
					for (var i:int=length;i--;) {
						removeDocument(IDocument(iProject.documents[i]), locations, dispatchEvents);
					}
				}
				
			}
		
			if (remote && iProject && iProject.id) { 
				// we need to create service
				if (deleteProjectService==null) {
					var service:WPService = new WPService();
					service = new WPService();
					service.host = getWPURL();
					service.addEventListener(WPService.RESULT, deleteProjectResultsHandler, false, 0, true);
					service.addEventListener(WPService.FAULT, deleteProjectFaultHandler, false, 0, true);
					deleteProjectService = service;
				}
				
				deleteProjectInProgress = true;
				
				deleteProjectService.id = iProject.id;
				deleteProjectService.deletePost();
			}
			else if (remote) {
				if (dispatchEvents) {
					dispatchProjectRemovedEvent(iProject);
					dispatchProjectDeletedEvent(true, iProject);
				}
				return false;
			}
			
			// get first or last open document and select the project it's part of
			if (!selectedProject) {
				// to do
			}

			if (!remote && dispatchEvents) {
				dispatchProjectRemovedEvent(iProject);
			}
			

			return true;
		}
		
		/**
		 * Create project from project data
		 * */
		public function createProjectFromData(projectData:IProjectData):IProject {
			var newProject:IProject = createProject();
			newProject.unmarshall(projectData);
			
			return newProject;
		}
		
		/**
		 * Create project from project XML data
		 * */
		public function createProjectFromXML(projectData:XML):IProject {
			var newProject:IProject = createProject();
			newProject.unmarshall(projectData);
			
			return newProject;
		}
		
		/**
		 * Create document from document data
		 * */
		public function createDocumentDataFromMetaData(documentData:IDocumentMetaData, overwrite:Boolean = false):IDocumentData {
			var newDocument:IDocumentData = new DocumentData();
			newDocument.unmarshall(documentData);
			
			return newDocument;
		}
		
		/**
		 * Create document from document data
		 * */
		public function createDocumentFromData(documentData:IDocumentData, overwrite:Boolean = false):IDocument {
			var newDocument:IDocument = createDocument(documentData.name, documentData.type);
			newDocument.unmarshall(documentData);
			
			return newDocument;
		}
		
		/**
		 * Create document from document meta data
		 * */
		public function createDocumentFromMetaData(documentMetaData:IDocumentMetaData, overwrite:Boolean = false):IDocument {
			var documentData:IDocumentData = createDocumentDataFromMetaData(documentMetaData, overwrite);
			var iDocument:IDocument = createDocumentFromData(documentData, overwrite);
			
			return iDocument;
		}
		
		/**
		 * Open saved documents if they exist or open a blank document
		 * */
		public function openInitialProjects():void {
			/*
			if (savedData && (savedData.projects.length>0 || savedData.documents.length>0)) {
				restoreSavedData(savedData);
			}
			else {
				createBlankDemoDocument();
			}
			*/
			
			if (!isUserLoggedIn) {
				if (savedData && (savedData.projects.length>0 || savedData.documents.length>0)) {
					openLocalProjects(savedData);
				}
				else {
					createBlankDemoDocument();
				}
			}
			else {
				getProjects();
				getAttachments();
			}
		}
		
		/**
		 * Creates a blank project
		 * */
		public function createBlankDemoDocument(projectName:String = null, documentName:String = null, type:Class = null, open:Boolean = true, dispatchEvents:Boolean = false, select:Boolean = true):IDocument {
			var newProject:IProject;
			var newDocument:IDocument;
			
			newProject = createProject(projectName); // create project
			addProject(newProject);       // add to projects array - shows up in application
			
			newDocument = createDocument(documentName); // create document
			addDocument(newDocument, newProject); // add to project and documents array - shows up in application
			
			openProject(newProject); // should open documents - maybe we should do all previous steps in this function???
			openDocument(newDocument, DocumentData.INTERNAL_LOCATION, true, true); // add to application and parse source code if any
			
			setProject(newProject); // selects project 
			
			return newDocument;
		}
		
		/**
		 * Creates a document
		 * */
		public function createDocument(name:String = null, Type:Object = null, project:IProject = null):IDocument {
			var hasDefinition:Boolean;
			var DocumentType:Object;
			var iDocument:IDocument;
			
			if (Type is String && Type!="null" && Type!="") {
				hasDefinition = ApplicationDomain.currentDomain.hasDefinition(String(Type));
				DocumentType = Document;
				
				if (hasDefinition) {
					DocumentType = ApplicationDomain.currentDomain.getDefinition(String(Type));
					iDocument = new DocumentType();
				}
				else {
					throw new Error("Type specified, '" + String(Type) + "' to create document is not found");
				}
			}
			else if (Type is Class) {
				iDocument = new Type();
			}
			else {
				iDocument = new Document();
			}
			
			iDocument.name = name ? name : "Document";
			iDocument.host = getWPURL();
			//document.documentData = document.marshall();
			return iDocument;
		}
		
		/**
		 * Adds a document to a project if set and adds it to the documents array
		 * */
		public function addDocument(iDocument:IDocument, project:IProject = null, overwrite:Boolean = false, dispatchEvents:Boolean = true):IDocument {
			var documentAlreadyExists:Boolean;
			var length:int;
			var documentAdded:Boolean;
			
			documentAlreadyExists = doesDocumentExist(iDocument.uid);
			
			// if not added already add to documents array
			if (!documentAlreadyExists) {
				documents.push(iDocument);
				documentAdded = true;
			}
			
			if (documentAlreadyExists && overwrite) {
				// check dates
				// remove from documents
				// remove from projects
				// add to documents
				// add to projects
				var documentToRemove:IDocument = getDocumentByUID(iDocument.uid);
				removeDocument(documentToRemove, DocumentData.LOCAL_LOCATION);// this is deleting the document
				// should there be a remove (internally) and delete method?
				
				//throw new Error("Document overwrite is not implemented yet");
				documentAdded = true;
			}
			
			if (project) {
				project.addDocument(iDocument, overwrite);
			}
			
			if (documentAdded && dispatchEvents) {
				dispatchDocumentAddedEvent(iDocument);
			}
			
			return iDocument;
		}
		
		/**
		 * Reverts a document to its open state
		 * */
		public function revertDocument(iDocument:IDocument, dispatchEvents:Boolean = true):Boolean {
			
			// TODO
			return false;
		}
		
		/**
		 * Removes a document from the documents array
		 * */
		public function removeDocument(iDocument:IDocument, locations:String = null, dispatchEvents:Boolean = true):Boolean {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var parentProject:IProject = iDocument.project;
			var documentsIndex:int = parentProject.documents.indexOf(iDocument);
			var removedDocument:IDocument;
			var remote:Boolean = getIsRemoteLocation(locations);
			
			if (documentsIndex!=-1) {
				// add remove document to project
				var removedDocuments:Array = parentProject.documents.splice(documentsIndex, 1);
				
				if (removedDocuments[0]==iDocument) {
					//log.info("Document removed successfully");
				}
			}
			
			closeDocument(iDocument);
			// check if document is open in tab navigator
			/*if (isDocumentOpen(iDocument)) {
				var closed:Boolean = closeDocument(iDocument);
				log.info("Closed " + iDocument.name);
			}*/
			
			if (remote && iDocument && iDocument.id) { 
				// we need to create service
				if (deleteDocumentService==null) {
					deleteDocumentService = new WPService();
					deleteDocumentService.addEventListener(WPService.RESULT, deleteDocumentResultsHandler, false, 0, true);
					deleteDocumentService.addEventListener(WPService.FAULT, deleteDocumentFaultHandler, false, 0, true);
				}
				
				deleteDocumentService.host = getWPURL();
				
				deleteDocumentInProgress = true;
				
				deleteDocumentService.id = iDocument.id
				deleteDocumentService.deletePost();
			}
			else if (remote) { // document not saved yet
				
				if (dispatchEvents) {
					dispatchDocumentRemovedEvent(iDocument);
					return true;
				}
			}
			else {
	
				if (dispatchEvents) {
					dispatchDocumentRemovedEvent(iDocument);
				}

			}
			
			// get first or last open document and select the project it's part of
			if (!this.selectedDocument) {
				// to do
			}
			
			return true;
		}
		
		/**
		 * Opens the document from it's document data. If the document is already open it selects it. 
		 * 
		 * It returns the document container. 
		 * */
		public function openDocumentByData(data:IDocumentData, showDocument:Boolean = true, dispatchEvents:Boolean = true):Object {
			var iDocument:IDocument = getDocumentByUID(data.uid);
			
			if (!iDocument) {
				iDocument = createDocumentFromData(data);
			}
			
			var result:Boolean = openDocument(iDocument, DocumentData.INTERNAL_LOCATION, showDocument, dispatchEvents);
			
			return result;
		}
		
		/**
		 * Print
		 * */
		public function print(data:Object, scaleType:String = FlexPrintJobScaleType.MATCH_WIDTH, printAsBitmap:Boolean = false):Object {
			var flexPrintJob:FlexPrintJob = new FlexPrintJob();
			var printableObject:IUIComponent;
			var scaleX:Number;
			var scaleY:Number;
			
			if (data is IDocument) {
				printableObject = IUIComponent(IDocument(data).instance)
			}
			else if (data is IUIComponent) {
				printableObject = IUIComponent(data);
			}
			else {
				Radiate.log.error("Printing failed: Object is not of accepted type.");
				return false;
			}
			
			if (data && "scaleX" in data) {
				scaleX = data.scaleX;
				scaleY = data.scaleY;
			}
			
			flexPrintJob.printAsBitmap = printAsBitmap;
			
			if (printAsBitmap && data is IBitmapDrawable) {
				var imageBitmapData:BitmapData = ImageSnapshot.captureBitmapData(IBitmapDrawable(data));
				var bitmapImage:BitmapImage = new BitmapImage();
                bitmapImage.source = new Bitmap(imageBitmapData);
				//data = bitmapImage;
			}
			
			// show OS print dialog
			// printJobStarted is false if user cancels OS print dialog
			var printJobStarted:Boolean = flexPrintJob.start();
			
			
			// if user cancels print job and we continue then the stage disappears! 
			// so we exit out (ie we don't do the try statement)
			// workaround if we set the scale it reappears 
			// so, scaleX and scaleY are set to NaN on the object when we try to print and it fails
			if (!printJobStarted) {
				log.error("Print job was not started");
				dispatchPrintCancelledEvent(data, flexPrintJob);
				return false;
			}
			
			try {
				//log.info("Print width and height: " + flexPrintJob.pageWidth + "x" + flexPrintJob.pageHeight);
				flexPrintJob.addObject(printableObject, scaleType);
				flexPrintJob.send();
				dispatchPrintCompleteEvent(data, flexPrintJob);
			}
			catch(e:Error) {
				// CHECK scale X and scale Y to see if they are null - see above
				if (data && "scaleX" in data && data.scaleX!=scaleX) {
					data.scaleX = scaleX;
					data.scaleY = scaleY;
				}
				
				// Printing failed: Error #2057: The page could not be added to the print job.
				Radiate.log.error("Printing failed: " + e.message);
				
				// TODO this should be print error event
				dispatchPrintCancelledEvent(data, flexPrintJob);
				return false;
			} 
			
			return true;
		}
		
		/**
		 * Import code. 
		 * 
		 * TODO: 
		 * - import mxml code to new document
		 * - import mxml code to existing document ovewrite current document
		 * - import document xml (wraps mxml application) 
		 * - import mxml to a container or group
		 * */
		public function importMXMLDocument(project:IProject, iDocument:IDocument, container:IVisualElement, code:String, dispatchEvents:Boolean = true):Boolean {
			var result:Object;
			var newDocument:Boolean;
			
			if (!iDocument) {
				iDocument = createDocument();
				newDocument = true;
				
				if (project) {
					addDocument(iDocument, project);
				}
			}
			
			
			if (!newDocument) {
				iDocument.parseSource(code, container);
			}
			else {
				iDocument.source = code;
				result = openDocument(iDocument, DocumentData.INTERNAL_LOCATION, true, dispatchEvents);
			}
			
			return result;
		}
		
		/**
		 * Opens the document. If the document is already open it selects it. 
		 * When the document loads (it's a blank application swf) then the mxml is parsed. Check the DocumentContainer class.  
		 * 
		 * It returns the document container. 
		 * */
		public function openDocument(iDocument:IDocument, locations:String = null, showDocumentInTab:Boolean = true, dispatchEvents:Boolean = true):Object {
			var documentContainer:DocumentContainer;
			var navigatorContent:NavigatorContent;
			var openingEventDispatched:Boolean;
			var containerTypeInstance:Object;
			var isAlreadyOpen:Boolean;
			var container:Object;
			var documentIndex:int;
			var previewName:String;
			var index:int;
			
			// NOTE: If the document is empty or all of the components are in the upper left hand corner
			// and they have no properties then my guess is that the application was never fully loaded 
			// or activated. this happens with multiple documents opening too quickly where some 
			// do not seem to activate. you see them activate when you select their tab for the first time
			// so then later if it hasn't activated, when the document is exported none of the components have
			// their properties or styles set possibly because Flex chose to defer applying them.
			// the solution is to make sure the application is fully loaded and activated
			// and also store a backup of the document MXML. 
			// that could mean waiting to open new documents until existing documents have 
			// loaded. listen for the application complete event (or create a parse and import event) 
			// ...haven't had time to do any of this yet
			
			isAlreadyOpen = isDocumentOpen(iDocument);
			
			if (dispatchEvents) {
				openingEventDispatched = dispatchDocumentOpeningEvent(iDocument);
				
				if (!openingEventDispatched) {
					//return false;
				}
			}
			
			if (isAlreadyOpen) {
				index = getDocumentTabIndex(iDocument);
				
				if (showDocumentInTab) {
					//showDocument(iDocument, false, false); // the next call will dispatch events
					showDocument(iDocument, false, dispatchEvents); // the next call will dispatch events
					setDocument(iDocument, dispatchEvents);
				}
				return documentsContainerDictionary[iDocument];
			}
			else {
				iDocument.open(locations);
			}
			
			// TypeError: Error #1034: Type Coercion failed: cannot convert 
			// com.flexcapacitor.components::DocumentContainer@114065851 to 
			// mx.core.INavigatorContent
			navigatorContent = new NavigatorContent();
			navigatorContent.percentWidth = 100;
			navigatorContent.percentHeight = 100;
			
			navigatorContent.label = iDocument.name ? iDocument.name : "Untitled";
			
			
			if (iDocument.containerType==null) {
				documentContainer = new DocumentContainer();
				documentContainer.percentWidth = 100;
				documentContainer.percentHeight = 100;
				
				documentsContainerDictionary[iDocument] = documentContainer;
				navigatorContent.addElement(documentContainer);
				documentContainer.iDocument = IDocument(iDocument);
			}
			else {
				// custom container
				containerTypeInstance = new iDocument.containerType();
				//containerTypeInstance.id = document.name ? document.name : "";
				containerTypeInstance.percentWidth = 100;
				containerTypeInstance.percentHeight = 100;
				
				documentsContainerDictionary[iDocument] = containerTypeInstance;
				navigatorContent.addElement(containerTypeInstance as IVisualElement);
				containerTypeInstance.iDocument = IDocument(iDocument);
			}
		
			if (documentsTabNavigator) {
				//documentIndex = !isPreview ? 0 : getDocumentIndex(document) + 1;
				documentsTabNavigator.addElement(navigatorContent);
			}
			documentIndex = getDocumentTabIndex(iDocument);
			
			// show document
			if (showDocumentInTab) {
				showDocument(iDocument, false, dispatchEvents);
				setDocument(iDocument, dispatchEvents);
			}
			
			return documentsContainerDictionary[iDocument];
		}
		
		/**
		 * Opens a preview of the document. If the document is already open it selects it. 
		 * 
		 * It returns the document container. 
		 * */
		public function openDocumentPreview(iDocument:IDocument, showDocument:Boolean = false, dispatchEvents:Boolean = true):Object {
			var documentContainer:DocumentContainer;
			var navigatorContent:NavigatorContent;
			var isAlreadyOpen:Boolean;
			var index:int;
			var iframe:IFrame;
			var containerTypeInstance:Object;
			var container:Object;
			var openingEventDispatched:Boolean;
			var documentIndex:int;
			var previewName:String;
			
			isAlreadyOpen = isDocumentPreviewOpen(iDocument);
			
			if (dispatchEvents) {
				openingEventDispatched = dispatchDocumentOpeningEvent(iDocument, true);
				if (!openingEventDispatched) {
					//return false;
				}
			}
			
			if (isAlreadyOpen) {
				index = getDocumentPreviewIndex(iDocument);
				
				if (showDocument) {
					showDocumentAtIndex(index, false); // the next call will dispatch events
					setDocument(iDocument, dispatchEvents);
				}
				return documentsPreviewDictionary[iDocument];
			}
			else {
				iDocument.isPreviewOpen = true;
			}
			
			// TypeError: Error #1034: Type Coercion failed: cannot convert 
			// com.flexcapacitor.components::DocumentContainer@114065851 to 
			// mx.core.INavigatorContent
			navigatorContent = new NavigatorContent();
			navigatorContent.percentWidth = 100;
			navigatorContent.percentHeight = 100;
			
			navigatorContent.label = iDocument.name ? iDocument.name : "Untitled";
			
			previewName = iDocument.name + " HTML";
			navigatorContent.label = previewName;
			
			if (iDocument.containerType) {
				containerTypeInstance = new iDocument.containerType();
				containerTypeInstance.id = iDocument.name ? iDocument.name : iframe.name; // should we be setting id like this?
				containerTypeInstance.percentWidth = 100;
				containerTypeInstance.percentHeight = 100;
				
				navigatorContent.addElement(containerTypeInstance as IVisualElement);
				documentsPreviewDictionary[iDocument] = containerTypeInstance;
			}
			else {
				// show HTML page
				iframe = new IFrame();
				iframe.id = iDocument.name ? iDocument.name : iframe.name; // should we be setting id like this?
				iframe.percentWidth = 100;
				iframe.percentHeight = 100;
				iframe.top = 20;
				iframe.left = 20;
				iframe.setStyle("backgroundColor", "#666666");
				
				navigatorContent.addElement(iframe);
				documentsPreviewDictionary[iDocument] = iframe;
			}
			
			
			// if preview add after original document location
			documentIndex = getDocumentTabIndex(iDocument) + 1; // add after
			documentsTabNavigator.addElementAt(navigatorContent, documentIndex);
			
			// show document
			if (showDocument) {
				showDocumentAtIndex(documentIndex, dispatchEvents);
				setDocument(iDocument, dispatchEvents);
			}
			
			return documentsPreviewDictionary[iDocument];
		}
		
		/**
		 * Checks if a document preview is open.
		 * @see isDocumentSelected
		 * */
		public function isDocumentPreviewOpen(document:IDocument):Boolean {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var tabContent:Object;
			var documentContainer:Object = documentsPreviewDictionary[document];
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					return true;
				}
			}
			
			return false;
		}
		
		/**
		 * Checks if document is open.
		 * @see isDocumentSelected
		 * */
		public function isDocumentOpen(document:IDocument, isPreview:Boolean = false):Boolean {
			var openTabs:Array;
			var tabCount:int;
			var tab:NavigatorContent;
			var tabContent:Object;
			var documentContainer:Object;
			
			if (!documentsTabNavigator) {
				return false;
			}
			
			openTabs = documentsTabNavigator.getChildren();
			tabCount = openTabs.length;
			documentContainer = isPreview ? documentsPreviewDictionary[document] : documentsContainerDictionary[document];
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					return true;
				}
			}
			
			return false;
			
		}
		
		/**
		 * Closes the current visible document regardless if it is a preview or not. 
		 * @see isDocumentSelected
		 * */
		public function closeVisibleDocument():Boolean {
			
			var selectedDocument:IDocument = getDocumentAtIndex(documentsTabNavigator.selectedIndex);
			var isPreview:Boolean = isPreviewDocumentVisible();
			
			return closeDocument(selectedDocument, isPreview);
			
		}
		
		/**
		 * Closes document if open.
		 * @see isDocumentSelected
		 * */
		public function closeDocument(iDocument:IDocument, isPreview:Boolean = false):Boolean {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var navigatorContent:NavigatorContent;
			var navigatorContentDocumentContainer:Object;
			var documentContainer:Object = isPreview ? documentsPreviewDictionary[iDocument] : documentsContainerDictionary[iDocument];
			
			
			// third attempt
			
			
			// second attempt
			
			if (documentContainer && documentContainer.owner) {
				// ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
				// 	at flash.display::DisplayObjectContainer/getChildIndex()
				//var index:int = documentsTabNavigator.getChildIndex(documentContainer.owner as DisplayObject);
				var contains:Boolean = documentsTabNavigator.contains(documentContainer.owner as DisplayObject);
				
				if (contains) {
					documentsTabNavigator.removeChild(documentContainer.owner);
					
					// close previews when the main document is closed
					if (!isPreview) {
						documentContainer = documentsPreviewDictionary[iDocument];
						
						if (documentContainer) {
							documentsTabNavigator.removeChild(documentContainer.owner);
						}
						
						iDocument.close();
						//removeDocument(iDocument);
						
						//var documentContainer:Object = isPreview ? documentsPreviewDictionary[iDocument] : documentsDictionary[iDocument];
						
						delete documentsContainerDictionary[iDocument];
						delete documentsPreviewDictionary[iDocument];
					}
					else {
						delete documentsPreviewDictionary[iDocument];
					}
					
					if (isPreview) {
						// TODO we must remove HTML from IFrame (inline css from previous iframes previews affects current preview)
					}
					
					documentsTabNavigator.validateNow();
					
				}
			}
			
			
			return true;
			// first attempt
			//log.info("Closing " + iDocument.name);
			for (var i:int;i<tabCount;i++) {
				navigatorContent = NavigatorContent(documentsTabNavigator.getChildAt(i));
				navigatorContentDocumentContainer = navigatorContent.numElements ? navigatorContent.getElementAt(0) : null;
				//log.info(" Checking tab " + tab.label);
				
				if (iDocument.name==navigatorContent.label) {
					//log.info(" Name Match " + iDocument.name);
					if (IDocumentContainer(navigatorContentDocumentContainer).iDocument==iDocument) {
						documentsTabNavigator.removeChild(navigatorContent);
						documentsTabNavigator.validateNow();
						
						return true;
					}
				}
				
				
				// oddly enough after we remove one child using the code below (note: see update)
				// the documentContainer in the documentsDictionary is no longer 
				// connected with the correct document data 
				// if we do this one at a time and remove one per second 
				// then it works but not many documents at a time (see removeProject)
				// so instead we are checking by name and then document reference 
				// in the code above this
				
				// Update: May have spoken too soon - could be problem because document 
				// was used as a variable name and it scoped to document on the UIComponent class :(
				
				if (navigatorContentDocumentContainer && navigatorContentDocumentContainer==documentContainer) {
					documentsTabNavigator.removeChild(navigatorContent);
					documentsTabNavigator.validateNow();
					return true;
				}
			}
			
			return false;
			
		}
		
		/**
		 * Checks if document is open and selected
		 * */
		public function isDocumentSelected(document:Object, isPreview:Boolean = false):Boolean {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var tabContent:Object;
			var documentIndex:int = -1;
			var documentContainer:Object = isPreview ? documentsPreviewDictionary[document] : documentsContainerDictionary[document];
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					documentIndex = i;
					break;
				}
			}
			

			if (documentsTabNavigator.selectedIndex==documentIndex) {
				return true;
			}
			
			return false;
			
		}
		
		/**
		 * Get visible document in documents tab navigator
		 * */
		public function getVisibleDocument():IDocument {
			var selectedTab:NavigatorContent = documentsTabNavigator ? documentsTabNavigator.selectedChild as NavigatorContent : null;
			var tabContent:Object = selectedTab && selectedTab.numElements ? selectedTab.getElementAt(0) : null;
			
			if (tabContent is IDocumentContainer) {
				var iDocument:IDocument = IDocumentContainer(tabContent).iDocument;
				return iDocument;
			}
			
			return null;
		}
		
		/**
		 * Get the index of the document in documents tab navigator
		 * */
		public function getDocumentTabIndex(document:Object, isPreview:Boolean = false):int {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var documentContainer:Object = isPreview ? documentsPreviewDictionary[document] : documentsContainerDictionary[document];
			var tabContent:Object;
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					return i;
				}
			}
			
			return -1;
		}
		
		/**
		 * Get the index of the document preview in documents tab navigator
		 * */
		public function getDocumentPreviewIndex(document:Object):int {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var documentContainer:Object = documentsPreviewDictionary[document];
			var tabContent:Object;
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					return i;
				}
			}
			
			return -1;
		}
		
		/**
		 * Get the document for the given application
		 * */
		public function getDocumentForApplication(application:Application):IDocument {
			var document:IDocument;
			
			for each (document in documentsContainerDictionary) {
				if (document.instance === application) {
					return document;
					break;
				}
			}
			return null;
		}
		
		/**
		 * Gets the document container for the document preview. 
		 * For example, a document can be previewed as an HTML page. 
		 * If we want to get the document that is previewing HTML then 
		 * we need to get the container of the preview.
		 * */
		public function getDocumentPreview(document:Object):Object {
			var documentContainer:Object = documentsPreviewDictionary[document];
			return documentContainer;
		}
		
		/**
		 * Returns if the visible document is a preview
		 * */
		public function isPreviewDocumentVisible():Boolean {
			var tabContainer:NavigatorContent = documentsTabNavigator.selectedChild as NavigatorContent;
			var tabContent:Object = tabContainer && tabContainer.numElements ? tabContainer.getElementAt(0) : null;
			var isPreview:Boolean;
			
			isPreview = DictionaryUtils.containsValue(documentsPreviewDictionary, tabContent);
			
			//if (!isDocument) {
			//	isDocument = DictionaryUtils.containsValue(documentsPreviewDictionary, tabContainer);
			//}
			
			return isPreview;
		}
		
		
		/**
		 * Selects the document in the tab navigator
		 * */
		public function showDocument(iDocumentData:IDocumentData, isPreview:Boolean = false, dispatchEvent:Boolean = true):Boolean {
			var documentIndex:int = getDocumentTabIndex(iDocumentData, isPreview);
			var result:Boolean;
			
			if (documentIndex!=-1) {
				result = showDocumentAtIndex(documentIndex, dispatchEvent);
			}
			
			return result;
		}
		
		
		/**
		 * Selects the document at the specifed index
		 * */
		public function showDocumentAtIndex(index:int, dispatchEvent:Boolean = true):Boolean {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var tabContent:Object;
			var document:IDocument;
			
			documentsTabNavigator.selectedIndex = index;
			
			tab = NavigatorContent(documentsTabNavigator.selectedChild);
			tabContent = tab && tab.numElements ? tab.getElementAt(0) : null;
			
			if (tabContent && tabContent is DocumentContainer && dispatchEvent) {
				document = getDocumentAtIndex(index);
				dispatchDocumentChangeEvent(DocumentContainer(tabContent).iDocument);
			}
			
			return documentsTabNavigator.selectedIndex == index;
		}
		
		/**
		 * Get the document at the index in the tab navigator
		 * */
		public function getDocumentAtIndex(index:int):IDocument {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var tabContent:Object;
			var document:IDocument;
			
			if (index<0) {
				return null;
			}
			
			tab = index < openTabs.length ? openTabs[index] : null;
			tabContent = tab.numElements ? tab.getElementAt(0) : null;
	
			for (var key:* in documentsContainerDictionary) {
				if (documentsContainerDictionary[key] === tabContent) {
					return key;
				}
			}
			
	
			for (key in documentsPreviewDictionary) {
				if (documentsPreviewDictionary[key] === tabContent) {
					return key;
				}
			}
			
			return null;
			
		}
		
		/**
		 * Get document by UID
		 * */
		public function getDocumentByUID(id:String):IDocument {
			var length:int = documents.length;
			var iDocument:IDocument;
			
			for (var i:int;i<length;i++) {
				iDocument = IDocument(documents[i]);
				
				if (id==iDocument.uid) {
					return iDocument;
				}
			}
			
			return null;
		}
		
		/**
		 * Check if document exists in documents array
		 * */
		public function doesDocumentExist(id:String):Boolean {
			var length:int = documents.length;
			var iDocument:IDocument;
			
			for (var i:int;i<length;i++) {
				iDocument = IDocument(documents[i]);
				
				if (id==iDocument.uid) {
					return true;
				}
			}
			
			return false;
		}
		
		/**
		 * Check if project exists in projects array. Pass in the UID not ID.
		 * */
		public function doesProjectExist(uid:String):Boolean {
			var length:int = projects.length;
			var iProject:IProject;
			
			for (var i:int;i<length;i++) {
				iProject = IProject(projects[i]);
				
				if (uid==iProject.uid) {
					return true;
				}
			}
			
			return false;
		}
		
		/**
		 * Get project by UID
		 * */
		public function getProjectByUID(id:String):IProject {
			var length:int = projects.length;
			var iProject:IProject;
			
			for (var i:int;i<length;i++) {
				iProject = IProject(projects[i]);
				
				if (id==iProject.uid) {
					return iProject;
				}
			}
			
			return null;
		}
		
		/**
		 * Get first project that owns this document
		 * */
		public function getDocumentProject(iDocument:IDocument):IProject {
			var projectsList:Array = getDocumentProjects(iDocument);
			var iProject:IProject;
			
			if (projectsList.length>0) {
				iProject = projectsList.shift();
			}
			
			return iProject;
		}
		
		/**
		 * Get a list of projects that own this document
		 * */
		public function getDocumentProjects(iDocument:IDocument):Array {
			var documentsLength:int;
			var projectDocument:IDocument;
			var projectLength:int = projects.length;
			var iProject:IProject;
			var projectDocuments:Array;
			var projectsList:Array = [];
			
			for (var A:int;A<length;A++) {
				iProject = IProject(projects[A]);
				projectDocuments = iProject.documents;
				
				for (var B:int;B<documentsLength;B++) {
					projectDocument = IDocument(projectDocuments[B]);
					
					if (projectDocuments.uid==iDocument.uid) {
						projectsList.push(iProject);
					}
				}
			}
			
			return projectsList;
		}
		
		
		/**
		 * Rename document
		 * */
		public function renameDocument(iDocument:IDocument, name:String):void {
			var tab:NavigatorContent;
			
			// todo check if name already exists
			iDocument.name = name;
			tab = getNavigatorByDocument(iDocument);
			
			if (iDocument.instance is Application) {
				setProperty(iDocument.instance, "pageTitle", name);
			}
			
			if (tab) {
				tab.label = iDocument.name;
			}
			
			dispatchDocumentRenameEvent(iDocument, name);
		}
		
		/**
		 * 
		 * */
		public function getNavigatorByDocument(iDocument:IDocument, isPreview:Boolean = false):NavigatorContent {
			var openTabs:Array = documentsTabNavigator.getChildren();
			var tabCount:int = openTabs.length;
			var tab:NavigatorContent;
			var tabContent:Object;
			var documentContainer:Object = isPreview ? documentsPreviewDictionary[iDocument] : documentsContainerDictionary[iDocument];
			
			for (var i:int;i<tabCount;i++) {
				tab = NavigatorContent(documentsTabNavigator.getChildAt(i));
				tabContent = tab.numElements ? tab.getElementAt(0) : null;
				
				if (tabContent && tabContent==documentContainer) {
					return tab;
				}
			}
			
			return null;
		}
		
		
		//----------------------------------
		//
		//  Persistant Data Management
		// 
		//----------------------------------
		
		/**
		 * Creates the saved data
		 * */
		public static function createSavedData():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SAVED_DATA_NAME in so.data && so.data[SAVED_DATA_NAME]!=null) {
						savedData = SavedData(so.data[SAVED_DATA_NAME]);
						//log.info("createSavedData:"+ObjectUtil.toString(savedData));
					}
					// does not contain property
					else {
						savedData = new SavedData();
					}
				}
				// data is null
				else {
					savedData = new SavedData();
				}
			}
			else {
				log.error("Could not get saved data. " + ObjectUtil.toString(result));
			}
			
			return true;
		}
		
		
		/**
		 * Creates the settings data
		 * */
		public static function createSettingsData():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SETTINGS_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SETTINGS_DATA_NAME in so.data && so.data[SETTINGS_DATA_NAME]!=null) {
						settings = Settings(so.data[SETTINGS_DATA_NAME]);
					}
					// does not contain settings property
					else {
						settings = new Settings();
					}
				}
				// data is null
				else {
					settings = new Settings();
				}
			}
			else {
				log.error("Could not get saved settings data. " + ObjectUtil.toString(result));
			}
			
			return true;
		}
		
		/**
		 * Get saved data
		 * */
		public function getSavedData():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			var data:SavedData;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SAVED_DATA_NAME in so.data) {
						data = SavedData(so.data[SAVED_DATA_NAME]);
						
						openLocalProjects(data);
					}
				}
			}
			else {
				log.error("Could not get saved data. " + ObjectUtil.toString(result));
			}
			
			return result;
		}
		
		/**
		 * Create new document. 
		 * */
		public function createNewDocument(name:String = null, type:Object = null, project:IProject = null):void {
			var newDocument:IDocument;
			var length:int;
			
			newDocument = createDocument(name, type);
			addDocument(newDocument, selectedProject, true, true);
			openDocument(newDocument, DocumentData.INTERNAL_LOCATION, true);
			/*
			
			if (project) {
				project.addDocument(iDocument, overwrite);
			}
			
			if (documentAdded && dispatchEvents) {
				dispatchDocumentAddedEvent(iDocument);
			}
			
			if (!selectedProject) {
				project = createProject(); // create project
				addProject(project);       // add to projects array - shows up in application
			}
			else {
				project = selectedProject;
			}
			
			newDocument = createDocument(name, type); // create document
			addDocument(newDocument, project); // add to project and documents array - shows up in application
			
			//openProject(newProject); // should open documents - maybe we should do all previous steps in this function???
			openDocument(newDocument, true, true); // add to application and parse source code if any
			
			setProject(project); // selects project 
			setDocument(newDocument);*/
		}
		
		/**
		 * Create new project. 
		 * */
		public function createNewProject(name:String = null, type:Object = null, project:IProject = null):void {
			var newProject:IProject;
			
			newProject = createProject(); // create project
			addProject(newProject);       // add to projects array - shows up in application
			
			openProject(newProject); // should open documents - maybe we should do all previous steps in this function???
			
			setProject(newProject); // selects project 
			
		}
		
		/**
		 * Create and add saved documents of array of type IDocumentData. 
		 * */
		public function createAndAddDocumentsData(documentsData:Array, add:Boolean = true):Array {
			var potentialDocuments:Array = [];
			var iDocumentMetaData:IDocumentMetaData;
			var iDocumentData:IDocumentData;
			var iDocument:IDocument;
			var length:int;
				
			// get documents and add them to the documents array
			
			// TRYING TO NOT create documents until they are needed
			// but then we have issues when we want to save
			if (documentsData && documentsData.length>0) {
				length = documentsData.length;
				
				for (var i:int;i<length;i++) {
					// TypeError: Error #1034: Type Coercion failed: cannot convert com.flexcapacitor.model::DocumentMetaData
					// to com.flexcapacitor.model.IDocumentData. check export and marshall options
					// saved as wrong data type
					iDocumentData = IDocumentData(documentsData[i]);
					
					// document doesn't exist - add it
					if (getDocumentByUID(iDocumentData.uid)==null) {
						iDocument = createDocumentFromData(iDocumentData);
						potentialDocuments.push(iDocument);
						
						if (add) {
							addDocument(iDocument);
						}
					}
					else {
						log.info("Document " + iDocumentData.name + " is already open.");
					}
				}
			}
			
			return potentialDocuments;
		}
		
		/**
		 * Create projects from array of type IProjectData
		 * */
		public function createAndAddProjectsData(projectsData:Array, add:Boolean = true):Array {
			var iProjectData:IProjectData;
			var potentialProjects:Array = [];
			var length:int;
			var iProject:IProject;
			
			// get projects and add them to the projects array
			if (projectsData && projectsData.length>0) {
				length = projectsData.length;
				
				for (var i:int;i<length;i++) {
					iProjectData = IProjectData(projectsData[i]);
					
					// project doesn't exist - add it
					if (getProjectByUID(iProjectData.uid)==null) {
						iProject = createProjectFromData(iProjectData);
						potentialProjects.push(iProject);
						
						if (add) {
							addProject(iProject);
						}
					}
					else {
						log.info("Project " + iProjectData.name + " is already open.");
					}
					
				}
			}
			
			return potentialProjects;
		}
		
		/**
		 * Restores projects and documents from local store
		 * Add all saved projects to projects array
		 * Add all saved documents to documents array
		 * Add documents to projects
		 * Open previously open projects
		 * Open previously open documents
		 * Select previously selected project
		 * Select previously selected document
		 * */
		public function openLocalProjects(data:SavedData):void {
			var projectsDataArray:Array;
			var potentialProjects:Array  = [];
			var potentialDocuments:Array = [];
			var savedDocumentsDataArray:Array;
			var potentialProjectsLength:int;
			var iProject:IProject;
			
			/*
			var iProjectData:IProjectData;
			var iDocumentData:IDocumentData;
			var iDocumentMetaData:IDocumentMetaData;
			var iDocument:IDocument;
			var iProjectDocument:IDocument;
			var iProjectDocumentsArray:Array;
			var iProjectDocumentsLength:int;
			var potentialDocumentsLength:int;
			var documentsDataArrayLength:int;*/
			
			// get list of projects and list of documents
			if (data) {
				
				// get projects and add them to the projects array
				projectsDataArray = data.projects;
				potentialProjects = createAndAddProjectsData(data.projects);
				
				// get documents and add them to the documents array
				// TRYING TO NOT create documents until they are needed
				// but then we have issues when we want to save or export
				createAndAddDocumentsData(data.documents);
				//savedDocumentsDataArray = data.documents; // should be potential documents?
				

				// go through projects and add documents to them
				if (potentialProjects.length>0) {
					potentialProjectsLength = potentialProjects.length;
					
					// loop through potentialProjectsLength objects
					for (var i:int;i<length;i++) {
						iProject = IProject(potentialProjects[i]);
						
						iProject.importDocumentInstances(documents);
					}
				}
				
				
				openPreviouslyOpenProjects();
				openPreviouslyOpenDocuments();
				showPreviouslyOpenProject();
				showPreviouslyOpenDocument();
				
			}
			else {
				// no saved data
				log.info("No saved data to restore");
			}
			
		}
		
		/**
		 * Show previously opened project
		 * */
		public function showPreviouslyOpenProject():void {
			var iProject:IProject;
			
			// Select last selected project
			if (settings.selectedProject) {
				iProject = getProjectByUID(settings.selectedProject.uid);
				
				if (iProject && iProject.isOpen) {
					log.info("Opening selected project " + iProject.name);
					setProject(iProject);
				}
			}
			else {
				if (selectedProject==null && projects && projects.length>0) {
					setProject(projects[0]);
				}
			}
		}
		
		/**
		 * Show previously opened document
		 * */
		public function showPreviouslyOpenDocument():void {
			var openDocuments:Array = settings.openDocuments;
			var iDocumentMetaData:IDocumentMetaData;
			var iDocument:IDocument;
			
			// Showing previously selected document
			if (settings.selectedDocument) {
				iDocument = getDocumentByUID(settings.selectedDocument.uid);
				
				if (iDocument && iDocument.isOpen) {
					log.info("Showing previously selected document " + iDocument.name);
					showDocument(iDocument);
					setDocument(iDocument);
				}
			}
		}
		
		/**
		 * Open previously opened documents
		 * */
		public function openPreviouslyOpenDocuments(project:IProject = null):void {
			var openDocuments:Array = settings.openDocuments;
			var iDocumentMetaData:IDocumentMetaData;
			var iDocument:IDocument;
			
			// open previously opened documents
			for (var i:int;i<openDocuments.length;i++) {
				iDocumentMetaData = IDocumentMetaData(openDocuments[i]);
				
				iDocument = getDocumentByUID(iDocumentMetaData.uid);
				
				if (iDocument) {
					
					if (project && project.documents.indexOf(iDocument)!=-1) {
						log.info("Opening project document " + iDocument.name);
						openDocument(iDocument, DocumentData.INTERNAL_LOCATION, false, true);
					}
					else if (project==null) {
						log.info("Opening document " + iDocument.name);
						openDocument(iDocument, DocumentData.INTERNAL_LOCATION, false, true);
					}
				}
				
			}
		}
		
		/**
		 * Open previously opened projects
		 * */
		public function openPreviouslyOpenProjects(locations:String = null):void {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var openProjects:Array = settings.openProjects;
			var iProject:IProject;
			var iProjectData:IProjectData;
			var openItemlength:int = openProjects.length;
			
			// open previously opened projects
			for (var i:int;i<openItemlength;i++) {
				iProjectData = IProjectData(openProjects[i]);
				iProject = getProjectByUID(iProjectData.uid);
				
				if (iProject) {
					log.info("Opening project " + iProject.name);
					openProject(iProject, locations, true);
				}
			}
		}
		
		/**
		 * Get saved settings data
		 * */
		public function getSettingsData():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SETTINGS_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SETTINGS_DATA_NAME in so.data) {
						settings = Settings(so.data[SETTINGS_DATA_NAME]);
					}
				}
			}
			else {
				log.error("Could not get saved data. " + ObjectUtil.toString(result));
			}
			
			return result;
		}
		
		/**
		 * Removed saved data
		 * */
		public function removeSavedData():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SAVED_DATA_NAME in so.data) {
						so.clear();
						log.info("Cleared saved data");
					}
				}
			}
			else {
				log.error("Could not remove saved data. " + ObjectUtil.toString(result));
			}
			
			return result;
		}
		
		/**
		 * Removed saved settings
		 * */
		public function removeSavedSettings():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SETTINGS_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				
				if (so.data) {
					if (SETTINGS_DATA_NAME in so.data) {
						so.clear(); // this clears the whole thing
						log.info("Cleared settings data");
					}
				}
			}
			else {
				log.error("Could not remove settings data. " + ObjectUtil.toString(result));
			}
			
			return result;
		}
		
		
		/**
		 * Save settings data
		 * */
		public function saveSettings():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SETTINGS_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				updateSettingsBeforeSave();
				so = SharedObject(result);
				so.setProperty(SETTINGS_DATA_NAME, settings);
				so.flush();
				
				//log.info("Saved Serrinfo: "+ ObjectUtil.toString(so.data));
			}
			else {
				log.error("Could not save data. " + ObjectUtil.toString(result));
				return false;
			}
			
			return true;
		}
		
		/**
		 * Save all projects and documents locally and remotely.
		 * Eventually, we will want to create a file options class that
		 * contains information on saving locally, to file, remotely, etc
		 * NOT FINISHED
		 * */
		public function save(locations:String = null, options:Object = null):void {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var local:Boolean = getIsLocalLocation(locations);
			var remote:Boolean = getIsRemoteLocation(locations);
			var localResult:Boolean;
			
			if (local) {
				local = saveProject(selectedProject, DocumentData.LOCAL_LOCATION);
			}
			
			if (remote) {
				if (remote && selectedProject is ISavable) {
					saveProjectInProgress = true
					ISavable(selectedProject).save(DocumentData.REMOTE_LOCATION, options);
					
					if (selectedProject is Project) {
						Project(selectedProject).addEventListener(SaveResultsEvent.SAVE_RESULTS, projectSaveResults, false, 0, true);
					}
				}
			}
			
			if (local) {
				// saved local successful
				if (localResult) {
					
				}
				else {
					// unsuccessful
				}
			}
			
			
			if (remote) {
				if (remote) {
					
				}
				else {
					
				}
			}
			
		}
		
		/**
		 * Save data
		 * */
		public function saveDataLocally():Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				updateSavedDataBeforeSave();
				so = SharedObject(result);
				so.setProperty(SAVED_DATA_NAME, savedData);
				
				try {
					so.flush();
				}
				catch (error:Error) {
					log.error(error.message);
					return false;
				}
				
			}
			else {
				log.error("Could not save data. " + ObjectUtil.toString(result));
				return false;
			}
			
			return true;
		}

		
		/**
		 * Project saved handler
		 * */
		public function projectSaveResults(event:IServiceEvent):void {
			var project:IProject = IProject(Event(event).currentTarget);
			saveProjectInProgress = false;
			
			if (project is EventDispatcher) {
				EventDispatcher(project).removeEventListener(SaveResultsEvent.SAVE_RESULTS, projectSaveResults);
			}
			
			if (event is SaveResultsEvent && SaveResultsEvent(event).successful) {
				setLastSaveDate();
			}
			
			dispatchProjectSavedEvent(IProject(Event(event).currentTarget));
		}
		
		/**
		 * Formatter for dates
		 * */
		public var dateFormatter:DateTimeFormatter = new DateTimeFormatter();
		
		/**
		 * Sets the last save date 
		 * */
		public function setLastSaveDate(date:Date = null):void {
			dateFormatter.dateStyle = DateTimeStyle.MEDIUM;
			if (!date) date = new Date();
			lastSaveDate = dateFormatter.format(date);
		}

		/**
		 * Save project
		 * */
		public function saveProject(project:IProject, locations:String = null):Boolean {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			
			//if (isUserLoggedIn && isUserConnected) {
			
			saveProjectInProgress = false;
			project.save(locations);
			//}
			
			if (project is EventDispatcher) {
				EventDispatcher(project).addEventListener(SaveResultsEvent.SAVE_RESULTS, projectSaveResults, false, 0, true);
			}
			
			// TODO add support to save after response from server 
			// because ID's may have been added from new documents
			var locallySaved:Boolean = saveProjectLocally(project);
			//project.saveCompleteCallback = saveData;
			return true;
		}

		/**
		 * Save project locally
		 * */
		public function saveProjectLocally(project:IProject, saveProjectDocuments:Boolean = true):Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				// todo - implement saveProjectDocuments
				updateSaveDataForProject(project);
				
				so = SharedObject(result);
				so.setProperty(SAVED_DATA_NAME, savedData);
				so.flush();
				//log.info("Saved Data: " + ObjectUtil.toString(so.data));
			}
			else {
				log.error("Could not save data. " + ObjectUtil.toString(result));
				//return false;
			}
			
			return true;
		}

		/**
		 * Save document. Uses constants, DocumentData.LOCAL_LOCATION, DocumentData.REMOTE_LOCATION, etc
		 * Separate them by ",". 
		 * */
		public function saveDocument(iDocument:IDocument, locations:String = null, options:Object = null):Boolean {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var saveLocally:Boolean = getIsLocalLocation(locations);
			var saveRemote:Boolean = getIsRemoteLocation(locations);
			var saveLocallySuccessful:Boolean;
			
			if (saveRemote && iDocument && iDocument is EventDispatcher) {
				EventDispatcher(iDocument).addEventListener(SaveResultsEvent.SAVE_RESULTS, documentSaveResultsHandler, false, 0, true);
			}
			
			saveLocallySuccessful = iDocument.save(locations, options);
			// TODO add support to save after response from server 
			// because ID's may have been added from new documents
			//saveData();
			//document.saveCompleteCallback = saveData;
			//saveDocumentLocally(document);
			return saveLocallySuccessful;
		}
		
		/**
		 * Returns true if location includes local shared object
		 * */
		public function getIsLocalLocation(value:String):Boolean {
			return value ? value.indexOf(DocumentData.LOCAL_LOCATION)!=-1 || value==DocumentData.ALL_LOCATIONS : false;
		}
		
		/**
		 * Returns true if location includes remote
		 * */
		public function getIsRemoteLocation(value:String):Boolean {
			return value ? value.indexOf(DocumentData.REMOTE_LOCATION)!=-1 || value==DocumentData.ALL_LOCATIONS : false;
		}
		
		/**
		 * Returns true if location includes file system
		 * */
		public function getIsFileLocation(value:String):Boolean {
			return value ? value.indexOf(DocumentData.FILE_LOCATION)!=-1 || value==DocumentData.ALL_LOCATIONS : false;
		}
		
		/**
		 * Returns true if location includes a database
		 * */
		public function getIsDataBaseLocation(value:String):Boolean {
			return value ? value.indexOf(DocumentData.FILE_LOCATION)!=-1 || value==DocumentData.ALL_LOCATIONS : false;
		}
		
		/**
		 * Returns true if location includes internal
		 * */
		public function getIsInternalLocation(value:String):Boolean {
			return value ? value.indexOf(DocumentData.INTERNAL_LOCATION)!=-1 || value==DocumentData.ALL_LOCATIONS : false;
		}
		
		/**
		 * Handles results from document save
		 * */
		protected function documentSaveResultsHandler(event:SaveResultsEvent):void {
			var document:IDocument = IDocument(event.currentTarget);
			
			if (document is Document) {
				Document(document).removeEventListener(SaveResultsEvent.SAVE_RESULTS, documentSaveResultsHandler);
			}
			
			setLastSaveDate();
			
			if (event.successful) {
				dispatchDocumentSaveCompleteEvent(document);
			}
			else {
				dispatchDocumentSaveFaultEvent(document);
			}
		}
		
		/**
		 * Save document
		 * */
		public function saveAllDocuments(saveLocations:String = ""):Boolean {
			var document:IDocument;
			var project:IProject;
			var length:int = documents.length;
			
			for (var i:int;i<length;i++) {
				document = documents[i];
				
				if (document.isChanged) {
					document.save(saveLocations);
					// TODO add support to save after response from server 
					// because ID's may have been added from new documents
					//saveData();
					//document.saveCompleteCallback = saveData;
					saveDocumentLocally(document);
				}
			}
			
			length = projects.length;
			for (i = 0;i<length;i++) {
				project = projects[i];
				
				if (project.isChanged) {
					project.save();
					// TODO add support to save after response from server 
					// because ID's may have been added from new documents
					//saveData();
					//document.saveCompleteCallback = saveData;
					saveProjectLocally(project);
				}
			}
			
			return true;
		}

		/**
		 * Save document as
		 * */
		public function saveDocumentAs(document:IDocument, extension:String = "html"):void {
			/*
			document.save();
			// TODO add support to save after response from server 
			// because ID's may have been added from new documents
			//saveData();
			//document.saveCompleteCallback = saveData;
			saveDocumentLocally(document);*/
			//return true;
		}

		/**
		 * Save file as
		 * */
		public function saveFileAs(data:Object, name:String = "", extension:String = "html"):FileReference {
			var fileName:String = name==null ? "" : name;
			fileName = fileName.indexOf(".")==-1 && extension ? fileName + "." + extension : fileName;
			
			// FOR SAVING A FILE (save as) WE MAY NOT NEED ALL THE LISTENERS WE ARE ADDING
			// add listeners
			var fileReference:FileReference = new FileReference();
			addFileListeners(fileReference);
			
			fileReference.save(data, fileName);
			
			return fileReference;
		}
		
		/**
		 * Adds file save as listeners. Rename or refactor
		 * */
		public function addFileListeners(dispatcher:IEventDispatcher):void {
			dispatcher.addEventListener(Event.CANCEL, cancelFileSaveAsHandler, false, 0, true);
			dispatcher.addEventListener(Event.COMPLETE, completeFileSaveAsHandler, false, 0, true);
		}
		
		/**
		 * Removes file save as listeners. Rename or refactor
		 * */
		public function removeFileListeners(dispatcher:IEventDispatcher):void {
			dispatcher.removeEventListener(Event.CANCEL, cancelFileSaveAsHandler);
			dispatcher.removeEventListener(Event.COMPLETE, completeFileSaveAsHandler);
		}
		
		/**
		 * File save as complete
		 * */
		public function completeFileSaveAsHandler(event:Event):void {
			removeFileListeners(event.currentTarget as IEventDispatcher);
			
			dispatchDocumentSaveCompleteEvent(selectedDocument);
		}
		
		/**
		 * Cancel file save as
		 * */
		public function cancelFileSaveAsHandler(event:Event):void {
			removeFileListeners(event.currentTarget as IEventDispatcher);
			
			dispatchDocumentSaveAsCancelEvent(selectedDocument);
		}
		
		/**
		 * Get document locally
		 * */
		public function getDocumentLocally(iDocumentData:IDocumentData):IDocumentData {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				so = SharedObject(result);
				//var data:Object = savedData;
				var documentsArray:Array = so.data.savedData.documents;
				var length:int = documentsArray.length;
				var documentData:IDocumentData;
				var found:Boolean;
				var foundIndex:int = -1;
				
				for (var i:int;i<length;i++) {
					documentData = IDocumentData(documentsArray[i]);
					
					if (documentData.uid == iDocumentData.uid) {
						found = true;
						foundIndex = i;
						
						break;
					}
				}
				
				return documentData;
			}
			else {
				log.error("Could not get saved data. " + ObjectUtil.toString(result));
			}
			
			return null;
		}
		
		/**
		 * Save document locally
		 * */
		public function saveDocumentLocally(document:IDocumentData):Boolean {
			var result:Object = SharedObjectUtils.getSharedObject(SAVED_DATA_NAME);
			var so:SharedObject;
			
			if (result is SharedObject) {
				updateSaveDataForDocument(document);
				so = SharedObject(result);
				so.setProperty(SAVED_DATA_NAME, savedData);
				so.flush();
				//log.info("Saved Data: " + ObjectUtil.toString(so.data));
			}
			else {
				log.error("Could not save data. " + ObjectUtil.toString(result));
				//return false;
			}
			
			return true;
		}
		
		/**
		 * Get settings
		 * */
		public function getSettings():Boolean {
			
			return true;
		}
		
		/**
		 * Get the latest settings and copy them into the settings object
		 * */
		public function updateSettingsBeforeSave():Settings {
			// get selected document
			// get selected project
			// get open projects
			// get open documents
			// get all documents
			// get all projects
			// save workspace settings
			// save preferences settings
			
			settings.lastOpened 		= new Date().time;
			//settings.modified 		= new Date().time;
			
			settings.openDocuments 		= getOpenDocumentsSaveData(true);
			settings.openProjects 		= getOpenProjectsSaveData(true);

			settings.selectedProject 	= selectedProject ? selectedProject.toMetaData() : null;
			settings.selectedDocument 	= selectedDocument ? selectedDocument.toMetaData() : null;
			
			settings.saveCount++;
			
			return settings;
		}
		
		/**
		 * Get the latest project and document data.
		 * */
		public function updateSavedDataBeforeSave():SavedData {
			// get selected document
			// get selected project
			// get open projects
			// get open documents
			// get all documents
			// get all projects
			// save workspace settings
			// save preferences settings
			
			savedData.modified 		= new Date().time;
			//settings.modified 		= new Date().time;
			savedData.documents 	= getSaveDataForAllDocuments();
			savedData.projects 		= getSaveDataForAllProjects();
			savedData.saveCount++;
			//savedData.resources 	= getResources();
			
			return savedData;
		}
		
		/**
		 * Get projects 
		 * */
		public function getProjects(status:String = WPService.STATUS_ANY, locations:String = null, count:int = 100):void {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			var loadLocally:Boolean = locations.indexOf(DocumentData.LOCAL_LOCATION)!=-1;
			var loadRemote:Boolean = locations.indexOf(DocumentData.REMOTE_LOCATION)!=-1;
			
			
			if (loadRemote) {
				// we need to create service
				if (getProjectsService==null) {
					var service:WPService = new WPService();
					service = new WPService();
					service.host = getWPURL();
					service.addEventListener(WPService.RESULT, getProjectsResultsHandler, false, 0, true);
					service.addEventListener(WPService.FAULT, getProjectsFaultHandler, false, 0, true);
					getProjectsService = service;
				}
				
				getProjectsInProgress = true;
				
				getProjectsService.getProjects(status, count);
			}
			
			if (loadLocally) {
				
			}
		}
		
		/**
		 * Get projects by user ID
		 * */
		public function getProjectsByUser(id:int, status:String = WPService.STATUS_ANY, locations:String = null, count:int = 100):void {
			if (locations==null) locations = DocumentData.REMOTE_LOCATION;
			if (status==null) status = WPService.STATUS_ANY;
			var loadLocally:Boolean = locations.indexOf(DocumentData.LOCAL_LOCATION)!=-1;
			var loadRemote:Boolean = locations.indexOf(DocumentData.REMOTE_LOCATION)!=-1;
			
			
			if (loadRemote) {
				// we need to create service
				if (getProjectsService==null) {
					var service:WPService = new WPService();
					service = new WPService();
					service.host = getWPURL();
					service.addEventListener(WPService.RESULT, getProjectsResultsHandler, false, 0, true);
					service.addEventListener(WPService.FAULT, getProjectsFaultHandler, false, 0, true);
					getProjectsService = service;
				}
				
				getProjectsInProgress = true;
				
				getProjectsService.getProjectsByUser(id, status, count);
				
			}
			
			if (loadLocally) {
				
			}
		}
		
		
		/**
		 * Login user 
		 * */
		public function login(username:String, password:String):void {
			
			// we need to create service
			if (loginService==null) {
				loginService = new WPService();
				loginService.addEventListener(WPService.RESULT, loginResultsHandler, false, 0, true);
				loginService.addEventListener(WPService.FAULT, loginFaultHandler, false, 0, true);
			}
			
			loginService.host = getWPURL();
				
			loginInProgress = true;
			
			loginService.loginUser(username, password);
			
		}
		
		/**
		 * Logout user 
		 * */
		public function logout():void {
			
			// we need to create service
			if (logoutService==null) {
				logoutService = new WPService();
				logoutService.addEventListener(WPService.RESULT, logoutResultsHandler, false, 0, true);
				logoutService.addEventListener(WPService.FAULT, logoutFaultHandler, false, 0, true);
			}
			
			logoutService.host = getWPURL();
			
			logoutInProgress = true;
			
			logoutService.logoutUser();
			
		}
		
		/**
		 * Register user 
		 * */
		public function register(username:String, email:String):void {
			
			// we need to create service
			if (registerService==null) {
				registerService = new WPService();
				registerService.addEventListener(WPService.RESULT, registerResultsHandler, false, 0, true);
				registerService.addEventListener(WPService.FAULT, registerFaultHandler, false, 0, true);
			}
			
			registerService.host = getWPURL();
			
			registerInProgress = true;
			
			registerService.registerUser(username, email);
			
		}
		
		/**
		 * Register site 
		 * */
		public function registerSite(blogName:String = "", blogTitle:String = "", isPublic:Boolean = false):void {
			
			// we need to create service
			if (registerService==null) {
				registerService = new WPService();
				registerService.addEventListener(WPService.RESULT, registerResultsHandler, false, 0, true);
				registerService.addEventListener(WPService.FAULT, registerFaultHandler, false, 0, true);
			}
			
			registerService.host = getWPURL();
			
			registerInProgress = true;
			
			registerService.registerSite(blogName, blogTitle, isPublic);
			
		}
		
		/**
		 * Register user and site 
		 * */
		public function registerUserAndSite(username:String, email:String, siteName:String = "", blogTitle:String = "", isPublic:Boolean = false, requireSiteName:Boolean = false):void {
			
			// we need to create service
			if (registerService==null) {
				registerService = new WPService();
				registerService.addEventListener(WPService.RESULT, registerResultsHandler, false, 0, true);
				registerService.addEventListener(WPService.FAULT, registerFaultHandler, false, 0, true);
			}
			
			registerService.host = getWPURL();
			
			registerInProgress = true;
			
			if (!requireSiteName) {
				if (siteName=="") {
					siteName = username;
				}
				
				if (blogTitle=="") {
					blogTitle = "A Radiate site";
				}
			}
			
			registerService.registerUserAndSite(username, email, siteName, blogTitle, isPublic);
			
		}
		
		/**
		 * Request lost password. Sends an email with instructions. 
		 * @param username or email address
		 * */
		public function lostPassword(usernameOrEmail:String):void {
			
			// we need to create service
			if (lostPasswordService==null) {
				lostPasswordService = new WPService();
				lostPasswordService.addEventListener(WPService.RESULT, lostPasswordResultsHandler, false, 0, true);
				lostPasswordService.addEventListener(WPService.FAULT, lostPasswordFaultHandler, false, 0, true);
			}
			
			lostPasswordService.host = getWPURL();
				
			lostPasswordInProgress = true;
			
			lostPasswordService.lostPassword(usernameOrEmail);
			
		}
		
		/**
		 * Reset or change password
		 * */
		public function changePassword(key:String, username:String, password:String, password2:String):void {
			
			// we need to create service
			if (changePasswordService==null) {
				changePasswordService = new WPService();
				changePasswordService.addEventListener(WPService.RESULT, changePasswordResultsHandler, false, 0, true);
				changePasswordService.addEventListener(WPService.FAULT, changePasswordFaultHandler, false, 0, true);
			}
			
			changePasswordService.host = getWPURL();
				
			changePasswordInProgress = true;
			
			changePasswordService.resetPassword(key, username, password, password2);
			
		}
		
		/**
		 * Get images from the server
		 * */
		public function getAttachments(id:int = 0):void {
			// get selected document
			
			// we need to create service
			if (getAttachmentsService==null) {
				getAttachmentsService = new WPService();
				getAttachmentsService.addEventListener(WPService.RESULT, getAttachmentsResultsHandler, false, 0, true);
				getAttachmentsService.addEventListener(WPService.FAULT, getAttachmentsFaultHandler, false, 0, true);
			}
			
			getAttachmentsService.host = getWPURL();
			
			if (id!=0) {
				getAttachmentsService.id = String(id);
			}
			
			getAttachmentsInProgress = true;
			
			
			getAttachmentsService.getAttachments(id);
		}
		
		/**
		 * Upload image to the server
		 * */
		public function uploadAttachment(data:Object, id:String, fileName:String = null, dataField:String = null, contentType:String = null):void {
			// get selected document
			
			// we need to create service
			if (uploadAttachmentService==null) {
				uploadAttachmentService = new WPAttachmentService();
				uploadAttachmentService.addEventListener(WPService.RESULT, uploadAttachmentResultsHandler, false, 0, true);
				uploadAttachmentService.addEventListener(WPService.FAULT, uploadAttachmentFaultHandler, false, 0, true);
				//uploadAttachmentService = service;
			}
			
			uploadAttachmentService.host = getWPURL();
		
			if (id!=null) {
				uploadAttachmentService.id = id;
			}
			
			uploadAttachmentInProgress = true;
			
			if (data is FileReference) {
				uploadAttachmentService.file = data as FileReference;
				uploadAttachmentService.uploadAttachment();
			}
			else if (data) {
				uploadAttachmentService.fileData = data as ByteArray;
				
				if (fileName) {
					uploadAttachmentService.fileName = fileName;
				}
				
				if (dataField) {
					uploadAttachmentService.dataField = dataField;
				}
				
				if (contentType) {
					uploadAttachmentService.contentType = contentType;
				}
				
				uploadAttachmentService.uploadAttachment();
			}
			else {
				Radiate.log.warn("No data or file is available for upload. Please select the file to upload.");
			}
			
		}
		
		/**
		 * Get projects
		 * */
		public function getLoggedInStatus():void {
			// get selected document
			var service:WPService;
			
			// we need to create service
			if (getProjectsService==null) {
				service = new WPService();
				service.host = getWPURL();
				service.addEventListener(WPService.RESULT, getLoggedInStatusResult, false, 0, true);
				service.addEventListener(WPService.FAULT, getLoggedInStatusFault, false, 0, true);
				getLoggedInStatusService = service;
			}
			
			getLoggedInStatusInProgress = true;
			
			getLoggedInStatusService.getLoggedInUser();
		}
		
		/**
		 * Handles result to check if user is logged in 
		 * */
		protected function getLoggedInStatusResult(event:WPServiceEvent):void {
			isUserConnected = true;
			var data:Object = event.data;

			updateUserInfo(data);
			
			getLoggedInStatusInProgress = false;
			
			dispatchLoginStatusEvent(isUserLoggedIn, data);
		}
		
		/**
		 * Updates the user information from data object from the server
		 * */
		public function updateUserInfo(data:Object):void {
			
			if (data && data is Object) {
				isUserLoggedIn = data.loggedIn;
				userAvatar = data.avatar;
				userDisplayName = data.displayName ? data.displayName : "guest";
				userID = data.id;
				userEmail = data.contact;
				user = data;
				
				if ("blogs" in user) {
					//userSites = user.blogs;
					userSites = [];
					for each (var blog:Object in user.blogs) {
						userSites.push(blog);
					}
					
					if (userSites.length>0) {
						userSitePath = userSites[0].path;
						WP_USER_PATH = userSitePath;
						WP_USER_PATH = WP_USER_PATH.replace(WP_PATH, "");
					}
					else {
						userSitePath = "";
						WP_USER_PATH = "";
					}
				}
			}
		}
		
		/**
		 * Handles fault when checking if user is logged in
		 * */
		protected function getLoggedInStatusFault(event:WPServiceEvent):void {
			var data:Object = event.data;
			isUserConnected = false;
			//isUserLoggedIn = false;
			
			getLoggedInStatusInProgress = false;
			
			dispatchLoginStatusEvent(isUserLoggedIn, data);
		}
		
		/**
		 * Results from call to get projects
		 * */
		public function getProjectsResultsHandler(event:IServiceEvent):void {
			
			//Radiate.log.info("Retrieved list of projects");
			
			var data:Object = event.data;
			
			getProjectsInProgress = false;
			
			dispatchGetProjectsListResultsEvent(data);
		}
		
		/**
		 * Open list of projects. Need to eventually convert from wordpress post data object to type classes.
		 * See getAttachmentsResultsHandler() 
		 * */
		public function openProjectsFromData(projectsData:Array):void {
			var length:int;
			var post:Object;
			var project:IProject
			var xml:XML;
			var isValid:Boolean;
			var firstProject:IProject;
			var potentialProjects:Array;
			
			length = projectsData.count;
			
			for (var i:int;i<length;i++) {
				post = potentialProjects.posts[i];
				isValid = XMLUtils.isValidXML(post.content);
				
				if (isValid) {
					xml = new XML(post.content);
					project = createProjectFromXML(xml);
					addProject(project);
					potentialProjects.push(project);
				}
				else {
					log.info("Could not import project:" + post.title);
				}
			}
			
			
			//potentialProjects = addSavedProjects(data.projects);
			
			if (potentialProjects.length>0) {
				openProject(potentialProjects[0]);
				setProject(potentialProjects[0]);
			}
		}
		
		/**
		 * Result from save fault
		 * */
		public function getProjectsFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			Radiate.log.info("Could not get list of projects");
			
			getProjectsInProgress = false;
			
			dispatchGetProjectsListResultsEvent(data);
		}
		
		/**
		 * Result get attachments
		 * */
		public function getAttachmentsResultsHandler(event:IServiceEvent):void {
			Radiate.log.info("Retrieved list of attachments");
			var data:Object = event.data;
			var potentialAttachments:Array = [];
			var length:int;
			var object:Object;
			var attachment:AttachmentData;
			
			if (data && data.count>0) {
				length = data.count;
				
				for (var i:int;i<length;i++) {
					object = data.attachments[i];
					
					if (String(object.mime_type).indexOf("image/")!=-1) {
						attachment = new ImageData();
						attachment.unmarshall(object);
					}
					else {
						attachment = new AttachmentData();
						attachment.unmarshall(object);
					}
					
					potentialAttachments.push(attachment);
				}
			}
			
			getAttachmentsInProgress = false;
			
			attachments = potentialAttachments;
			
			dispatchAttachmentsResultsEvent(true, attachments);
		}
		
		/**
		 * Result from attachments fault
		 * */
		public function getAttachmentsFaultHandler(event:IServiceEvent):void {
			
			Radiate.log.info("Could not get list of attachments");
			
			getAttachmentsInProgress = false;
			
			//dispatchEvent(saveResultsEvent);
			dispatchAttachmentsResultsEvent(false, []);
		}
		
		/**
		 * Result upload attachment
		 * */
		public function uploadAttachmentResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Upload attachment");
			var data:Object = event.data;
			var potentialAttachments:Array = [];
			var successful:Boolean = data && data.status && data.status=="ok" ? true : false;
			var length:int;
			var object:Object;
			var attachment:AttachmentData;
			var asset:AttachmentData;
			var remoteAttachments:Array = data && data.post && data.post.attachments ? data.post.attachments : []; 
			var containsName:Boolean;
			var assetsLength:int;
			
			if (remoteAttachments.length>0) {
				length = remoteAttachments.length;
				
				for (var i:int;i<length;i++) {
					object = remoteAttachments[i];
					
					if (String(object.mime_type).indexOf("image/")!=-1) {
						attachment = new ImageData();
						attachment.unmarshall(object);
					}
					else {
						attachment = new AttachmentData();
						attachment.unmarshall(object);
					}
					
					potentialAttachments.push(attachment);
					
					//attachments = potentialAttachments;
					assetsLength = assets.length;
					j = 0;
					
					for (var j:int;j<assetsLength;j++) {
						asset = assets.getItemAt(j) as AttachmentData;
						containsName = asset ? asset.name.indexOf(attachment.name)==0 : false;
						
						// this is not very robust but since uploading only supports one at a time 
						// it should be fine. when supporting multiple uploading, keep
						// track of items being uploaded
						if (containsName && asset.id==null) {
							asset.unmarshall(attachment);
							
							var documentLength:int = documents.length;
							k = 0;
							
							for (var k:int;k<documentLength;k++) {
								var iDocument:IDocument = documents[k] as IDocument;
								
								if (iDocument) {
									DisplayObjectUtils.walkDownComponentTree(iDocument.componentDescription, replaceBitmapData, [asset]);
								}
							}
							
							break;
						}
					}
				}
			}
			
			
			uploadAttachmentInProgress = false;
			
			dispatchUploadAttachmentResultsEvent(successful, potentialAttachments, data.post);
		}
		
		/**
		 * Replaces occurances where the bitmapData in Image and BitmapImage have
		 * been uploaded to the server and we now want to point the image to a URL
		 * rather than bitmap data
		 * */
		public function replaceBitmapData(component:ComponentDescription, imageData:ImageData):void {
			var instance:Object;
			
			if (imageData && component && component.instance) {
				instance = component.instance;
				
				if (instance is Image || instance is BitmapImage) {
					if (instance.source == imageData.bitmapData) {
						Radiate.setProperty(instance, "source", imageData.url);
					}
				}
			}
		}
		
		/**
		 * Result from upload attachment fault
		 * */
		public function uploadAttachmentFaultHandler(event:IServiceEvent):void {
			Radiate.log.info("Upload attachment fault");
			
			uploadAttachmentInProgress = false;
			
			//dispatchEvent(saveResultsEvent);
			dispatchUploadAttachmentResultsEvent(false, [], event.data);
		}
		
		/**
		 * Login results handler
		 * */
		public function loginResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Login results");
			var data:Object = event.data;
			var loggedIn:Boolean;
			
			if (data && data is Object) {
				
				loggedIn = data.loggedIn==true;
				
				updateUserInfo(data);
			}
			
			loginInProgress = false;
			
			
			dispatchLoginResultsEvent(loggedIn, data);
		}
		
		/**
		 * Result from login fault
		 * */
		public function loginFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server to login. ");
			
			loginInProgress = false;
			
			dispatchLoginResultsEvent(false, data);
		}
		
		/**
		 * Logout results handler
		 * */
		public function logoutResultsHandler(event:IServiceEvent):void {
			Radiate.log.info("Logout results");
			var data:Object = event.data;
			var loggedOut:Boolean;
			
			if (data && data is Object) {
				
				loggedOut = data.loggedIn==false;
				
				updateUserInfo(data);
			}
			
			logoutInProgress = false;
			
			
			dispatchLogoutResultsEvent(loggedOut, data);
		}
		
		/**
		 * Result from logout fault
		 * */
		public function logoutFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server to logout. ");
			
			logoutInProgress = false;
			
			dispatchLogoutResultsEvent(false, data);
		}
		
		/**
		 * Register results handler
		 * */
		public function registerResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Register results");
			var data:Object = event.data;
			var successful:Boolean;
			
			if (data && data is Object && "created" in data) {
				
				successful = data.created;
				
			}
			
			registerInProgress = false;
			
			
			dispatchRegisterResultsEvent(successful, data);
		}
		
		/**
		 * Result from register fault
		 * */
		public function registerFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server to register. ");
			
			registerInProgress = false;
			
			dispatchRegisterResultsEvent(false, data);
		}
		
		/**
		 * Register results handler
		 * */
		public function changePasswordResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Change password results");
			var data:Object = event.data;
			var successful:Boolean;
			
			if (data && data is Object && "created" in data) {
				
				successful = data.created;
				
			}
			
			changePasswordInProgress = false;
			
			
			dispatchChangePasswordResultsEvent(successful, data);
		}
		
		/**
		 * Result from change password fault
		 * */
		public function changePasswordFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server. " + event.faultEvent.toString());
			
			changePasswordInProgress = false;
			
			dispatchChangePasswordResultsEvent(false, data);
		}
		
		/**
		 * Lost password results handler
		 * */
		public function lostPasswordResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Change password results");
			var data:Object = event.data;
			var successful:Boolean;
			
			if (data && data is Object && "created" in data) {
				successful = data.created;
			}
			
			lostPasswordInProgress = false;
			
			
			dispatchLostPasswordResultsEvent(successful, data);
		}
		
		/**
		 * Result from lost password fault
		 * */
		public function lostPasswordFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server. " + event.faultEvent.toString());
			
			lostPasswordInProgress = false;
			
			dispatchLostPasswordResultsEvent(false, data);
		}
		
		/**
		 * Delete project results handler
		 * */
		public function deleteProjectResultsHandler(event:IServiceEvent):void {
			//Radiate.log.info("Delete project results");
			var data:Object = event.data;
			var status:Boolean;
			var successful:Boolean;
			var error:String;
			var message:String;
			
			if (data && data is Object) {
				//status = data.status==true;
			}
			
			deleteProjectInProgress = false;
			
			if (data && data is Object && "status" in data) {
				
				successful = data.status!="error";
			}
			
			//Include 'id' or 'slug' var in your request.
			if (event.faultEvent is IOErrorEvent) {
				message = "Are you connected to the internet? ";
				
				if (event.faultEvent is IOErrorEvent) {
					message = IOErrorEvent(event.faultEvent).text;
				}
				else if (event.faultEvent is SecurityErrorEvent) {
					
					if (SecurityErrorEvent(event.faultEvent).errorID==2048) {
						
					}
					
					message += SecurityErrorEvent(event.faultEvent).text;
				}
			}
			
			
			//dispatchProjectRemovedEvent(null);
			
			dispatchProjectDeletedEvent(successful, data);
		}
		
		/**
		 * Result from delete project fault
		 * */
		public function deleteProjectFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server to delete the project. ");
			
			deleteProjectInProgress = false;
			
			dispatchProjectDeletedEvent(false, data);
		}
		
		/**
		 * Delete document results handler
		 * */
		public function deleteDocumentResultsHandler(event:IServiceEvent):void {
			//..Radiate.log.info("Delete document results");
			var data:Object = event.data;
			//var status:Boolean;
			var successful:Boolean;
			var error:String;
			var message:String;
			
			
			if (data && data is Object && "status" in data) {
				successful = data.status!="error";
			}
			
			deleteDocumentInProgress = false;
			deleteAttachmentInProgress = false;
			
			//Include 'id' or 'slug' var in your request.
			if (event.faultEvent is IOErrorEvent) {
				message = "Are you connected to the internet? ";
				
				if (event.faultEvent is IOErrorEvent) {
					message = IOErrorEvent(event.faultEvent).text;
				}
				else if (event.faultEvent is SecurityErrorEvent) {
					
					if (SecurityErrorEvent(event.faultEvent).errorID==2048) {
						
					}
					
					message += SecurityErrorEvent(event.faultEvent).text;
				}
			}
			
			//status = message;
			
			//dispatchDocumentRemovedEvent(null);
			
			dispatchDocumentDeletedEvent(successful, data);
		}
		
		/**
		 * Result from delete project fault
		 * */
		public function deleteDocumentFaultHandler(event:IServiceEvent):void {
			var data:Object = event.data;
			
			Radiate.log.info("Could not connect to the server to delete the document. ");
			
			deleteDocumentInProgress = false;
			
			dispatchDocumentDeletedEvent(false, data);
		}

		
		/**
		 * Check if the project has changed and mark changed if it is. 
		 * */
		public function checkIfProjectHasChanged(iProject:IProject):Boolean {
			
			var isChanged:Boolean = iProject.checkProjectHasChanged();
			
			return isChanged;
		}
		
		/**
		 * Updates the saved data with the changes from the document passed in
		 * */
		public function updateSaveDataForDocument(iDocumentData:IDocumentData, metaData:Boolean = false):SavedData {
			var documentsArray:Array = savedData.documents;
			var length:int = documentsArray.length;
			var documentMetaData:IDocumentMetaData;
			var found:Boolean;
			var foundIndex:int = -1;
			
			for (var i:int;i<length;i++) {
				documentMetaData = IDocumentMetaData(documentsArray[i]);
				//Radiate.log.info("Exporting document " + iDocument.name);
				
				if (documentMetaData.uid == iDocumentData.uid) {
					found = true;
					foundIndex = i;
				}
			}
			
			if (found) {
				
				if (metaData) {
					documentsArray[foundIndex] = iDocumentData.toMetaData();
				}
				else {
					documentsArray[foundIndex] = iDocumentData.marshall();
				}
			}
			else {
				if (metaData) {
					documentsArray.push(iDocumentData.toMetaData());
				}
				else {
					documentsArray.push(iDocumentData.marshall());
				}
			}
			
			
			return savedData;
		}
		
		/**
		 * Updates the saved data with the changes from the project passed in
		 * */
		public function updateSaveDataForProject(iProject:IProject, metaData:Boolean = false):SavedData {
			var projectsArray:Array = savedData.projects;
			var length:int = projectsArray.length;
			var documentMetaData:IDocumentMetaData;
			var found:Boolean;
			var foundIndex:int = -1;
			
			for (var i:int;i<length;i++) {
				documentMetaData = IDocumentData(projectsArray[i]);
				//Radiate.log.info("Exporting document " + iDocument.name);
				
				if (documentMetaData.uid == iProject.uid) {
					found = true;
					foundIndex = i;
				}
			}
			
			if (found) {
				
				if (metaData) {
					projectsArray[foundIndex] = iProject.toMetaData();
				}
				else {
					projectsArray[foundIndex] = iProject.marshall();
				}
			}
			else {
				if (metaData) {
					projectsArray.push(iProject.toMetaData());
				}
				else {
					projectsArray.push(iProject.marshall());
				}
			}
			
			
			return savedData;
		}
		
		/**
		 * Get a list of documents. If open is set to true then gets only open documents.
		 * */
		public function getOpenDocumentsSaveData(metaData:Boolean = false):Array {
			var documentsArray:Array = getSaveDataForAllDocuments(true, metaData);
			return documentsArray;
		}
		
		/**
		 * Get a list of documents data for storage by project. If open is set to true then only returns open documents.
		 * */
		public function getDocumentsSaveDataByProject(project:IProject, open:Boolean = false):Array {
			var documentsArray:Array = project.getSavableDocumentsData(open);
			
			return documentsArray;
		}
		
		/**
		 * Get a list of all documents data for storage. If open is set to 
		 * true then only returns open documents.
		 * */
		public function getSaveDataForAllDocuments(open:Boolean = false, metaData:Boolean = false):Array {
			var length:int = projects.length;
			var documentsArray:Array = [];
			var iProject:IProject;
			
			for (var i:int;i<length;i++) {
				iProject = projects[i];
				documentsArray = documentsArray.concat(iProject.getSavableDocumentsData(open, metaData));
			}
			
			return documentsArray;
		}
		
		
		/**
		 * Get a list of projects that are open. 
		 * If meta data is true only returns meta data. 
		 * */
		public function getOpenProjectsSaveData(metaData:Boolean = false):Array {
			var projectsArray:Array = getSaveDataForAllProjects(true, metaData);
			
			return projectsArray;
		}
		
		/**
		 * Get an array of projects serialized for storage. 
		 * If open is set to true then only returns open projects.
		 * If meta data is true then only returns meta data. 
		 * */
		public function getSaveDataForAllProjects(open:Boolean = false, metaData:Boolean = false):Array {
			var projectsArray:Array = [];
			var length:int = projects.length;
			var iProject:IProject;
			
			for (var i:int; i < length; i++) {
				iProject = IProject(projects[i]);
				
				if (open) {
					if (iProject.isOpen) {
						if (metaData) {
							projectsArray.push(iProject.toMetaData());
						}
						else {
							projectsArray.push(iProject.marshall());
						}
					}
				}
				else {
					if (metaData) {
						projectsArray.push(iProject.toMetaData());
					}
					else {
						projectsArray.push(iProject.marshall());
					}
				}
			}
			
			
			return projectsArray;
		}
		
		/**
		 * Get an array of projects serialized for storage. 
		 * If open is set to true then only returns open projects.
		 * If meta data is true then only returns meta data. 
		 * */
		public function saveProjectsRemotely(open:Boolean = false):Array {
			var projectsArray:Array = [];
			var length:int = projects.length;
			var iProject:IProject;
			
			for (var i:int; i < length; i++) {
				iProject = IProject(projects[i]);
				
				if (open) {
					if (iProject.isOpen) {
						iProject.save();
					}
				}
				else {
					iProject.save();
				}
			}
			
			
			return projectsArray;
		}
		
		//----------------------------------
		//
		//  History Management
		// 
		//----------------------------------
		
		// NOTE: THIS IS WRITTEN THIS WAY TO WORK WITH FLEX STATES AND TRANSITIONS
		// there is probably a better way but I am attempting to use the flex sdk's
		// own code to apply changes. we could extract that code, create commands, 
		// etc but it seemed like less work and less room for error at the time
		
		// update oct 27, 2013
		// i think it would be better to move these calls and data to the document class
		// then different document types can handle undo, redo in the way that best 
		// makes sense to it's own needs. 
		// For example, an text editor will handle undo redo differently than 
		// a design or application document. 
		// 
		// and another way we could do history management is create a sequence and 
		// add actions to it (SetAction, AddItem, RemoveItem, etc)
		// that would probably enable easy to use automation and playback
		// if we had proxied these methods here we could have extended the default
		// document and over wrote the methods to try the sequence method
		
		public static var REMOVE_ITEM_DESCRIPTION:String = "Remove";
		public static var ADD_ITEM_DESCRIPTION:String = "Add";
		private static var BEGINNING_OF_HISTORY:String;
		
		/**
		 * Collection of items in the property change history
		 * */
		[Bindable]
		public static var history:ArrayCollection = new ArrayCollection();
		
		/**
		 * Dictionary of property change objects
		 * */
		public static var historyEventsDictionary:Dictionary = new Dictionary(true);
		
		
		/**
		 * Travel to the specified history index.
		 * Going to fast may cause some issues. Need to test thoroughly 
		 * We may need to call validateNow somewhere and set usePhasedInstantiation?
		 * */
		public static function goToHistoryIndex(index:int, dispatchEvents:Boolean = false):int {
			var document:IDocument = instance.selectedDocument;
			var newIndex:int = index;
			var oldIndex:int = historyIndex;
			var time:int = getTimer();
			var currentIndex:int;
			var difference:int;
			var layoutManager:ILayoutManager = LayoutManager.getInstance();
			var phasedInstantiation:Boolean = layoutManager.usePhasedInstantiation;
			
			layoutManager.usePhasedInstantiation = false;
			
			if (newIndex<oldIndex) {
				difference = oldIndex - newIndex;
				for (var i:int;i<difference;i++) {
					currentIndex = undo(dispatchEvents, dispatchEvents);
				}
			}
			else if (newIndex>oldIndex) {
				difference = oldIndex<0 ? newIndex+1 : newIndex - oldIndex;
				for (var j:int;j<difference;j++) {
					currentIndex = redo(dispatchEvents, dispatchEvents);
				}
			}
			
			layoutManager.usePhasedInstantiation = phasedInstantiation;
			
			history.refresh();
			historyIndex = getHistoryIndex();
			
			instance.dispatchHistoryChangeEvent(historyIndex, oldIndex);
			
			
			return currentIndex;
		}
		
		/**
		 * Undo last change. Returns the current index in the changes array. 
		 * The property change object sets the property "reversed" to 
		 * true.
		 * Going too fast causes some issues (call validateNow somewhere)?
		 * I think the issue with RangeError: Index 2 is out of range.
		 * is that the History List does not always do the first item in the 
		 * List. So we need to add a first item that does nothing, like a
		 * open history event. 
		 * OR we need to wait. If we could use callLater and not use validateNow
		 * I think it may solve some issues and not lock the UI
		 * */
		public static function undo(dispatchEvents:Boolean = false, dispatchForApplication:Boolean = true):int {
			var changeIndex:int = getPreviousHistoryIndex(); // index of next change to undo 
			var currentIndex:int = getHistoryIndex();
			var historyLength:int = history.length;
			var historyEvent:HistoryEventItem;
			var currentDocument:IDocument = instance.selectedDocument;
			var currentTargetDocument:Application = currentDocument.instance as Application;
			var setStartValues:Boolean = true;
			var historyItem:HistoryEvent;
			var affectsDocument:Boolean;
			var historyEvents:Array;
			var dictionary:Dictionary;
			var reverseItems:AddItems;
			var eventTargets:Array;
			var eventsLength:int;
			var targetsLength:int;
			var addItems:AddItems;
			var added:Boolean;
			var removed:Boolean;
			var action:String;
			var isInvalid:Boolean;
			
			// no changes
			if (!historyLength) {
				return -1;
			}
			
			// all changes have already been undone
			if (changeIndex<0) {
				if (dispatchEvents && instance.hasEventListener(RadiateEvent.BEGINNING_OF_UNDO_HISTORY)) {
					instance.dispatchEvent(new RadiateEvent(RadiateEvent.BEGINNING_OF_UNDO_HISTORY));
				}
				
				return -1;
			}
			
			// get current change to be redone
			historyItem = history.length ? history.getItemAt(changeIndex) as HistoryEvent : null;
			historyEvents = historyItem.historyEventItems;
			eventsLength = historyEvents.length;
			
			
			// loop through changes
			for (var i:int=eventsLength;i--;) {
				//changesLength = changes ? changes.length: 0;
				
				historyEvent = historyEvents[i];
				addItems = historyEvent.addItemsInstance;
				action = historyEvent.action;//==RadiateEvent.MOVE_ITEM && addItems ? RadiateEvent.MOVE_ITEM : RadiateEvent.PROPERTY_CHANGE;
				affectsDocument = dispatchForApplication && historyEvent.targets.indexOf(currentTargetDocument)!=-1;
				
				// undo the add
				if (action==RadiateEvent.ADD_ITEM) {
					eventTargets = historyEvent.targets;
					targetsLength = eventTargets.length;
					dictionary = historyEvent.reverseAddItemsDictionary;
					
					for (var j:int=0;j<targetsLength;j++) {
						reverseItems = dictionary[eventTargets[j]];
						addItems.remove(null);
						
						// check if it's reverse or property changes
						if (reverseItems) {
							reverseItems.apply(reverseItems.destination as UIComponent);
							
							// was it added - can be refactored
							if (reverseItems.destination==null) {
								added = true;
							}
						}
					}
					
					historyEvent.reversed = true;
					
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchRemoveItemsEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
				}
				
				// undo the move - (most likely an add action with x and y changes)
				if (action==RadiateEvent.MOVE_ITEM) {
					eventTargets = historyEvent.targets;
					targetsLength = eventTargets.length;
					dictionary = historyEvent.reverseAddItemsDictionary;
					
					for (j=0;j<targetsLength;j++) {
						reverseItems = dictionary[eventTargets[j]];
						
						// check if it's remove items or property changes
						if (reverseItems) {
							isInvalid = LayoutManager.getInstance().isInvalid();
							if (isInvalid) {
								LayoutManager.getInstance().validateNow();
								LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 1.") : 0;
							}
							
							addItems.remove(null);
							isInvalid = LayoutManager.getInstance().isInvalid();
							if (isInvalid) {
								LayoutManager.getInstance().validateNow();
								LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 2.") : 0;
							}
							reverseItems.apply(reverseItems.destination as UIComponent);
							
							if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
								instance.dispatchRemoveItemsEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
							}
							
							// was it added - note: can be refactored
							if (reverseItems.destination==null) {
								added = true;
							}
						}
						else { // property change
							applyChanges(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties, historyEvent.styles,
								setStartValues);
							historyEvent.reversed = true;
							
							if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
								instance.dispatchPropertyChangeEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
							}
						}
					}
					
					historyEvent.reversed = true;
				}
				// undo the remove
				else if (action==RadiateEvent.REMOVE_ITEM) {
					isInvalid = LayoutManager.getInstance().isInvalid();
					if (isInvalid) {
						LayoutManager.getInstance().validateNow();
						LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 3") : 0;
					}
					addItems.apply(addItems.destination as UIComponent);
					historyEvent.reversed = true;
					removed = true;
					
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchAddEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
				}
				// undo the property changes
				else if (action==RadiateEvent.PROPERTY_CHANGED) {
				
					applyChanges(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties, historyEvent.styles,
						setStartValues);
					historyEvent.reversed = true;
					
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchPropertyChangeEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
				}
			}
			
			historyItem.reversed = true;
			
			// select the target
			if (selectTargetOnHistoryChange) {
				if (added) { // item was added and now unadded - select previous
					if (currentIndex>0) {
						instance.setTarget(HistoryEvent(history.getItemAt(currentIndex-1)).targets, true);
					}
					else {
						instance.setTarget(currentTargetDocument, true);
					}
				}
				else if (removed) {
					instance.setTargets(historyEvent.targets, true);
				}
				else {
					instance.setTargets(historyEvent.targets, true);
				}
			}
			
			if (eventsLength) {
				historyIndex = getHistoryIndex();
				
				if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
					instance.dispatchHistoryChangeEvent(historyIndex, currentIndex);
				}
				return changeIndex-1;
			}
			
			return historyLength;
		}
		
		/**
		 * Redo last change. See notes in undo method. 
		 * @see undo
		 * */
		public static function redo(dispatchEvents:Boolean = false, dispatchForApplication:Boolean = true):int {
			var currentDocument:IDocument = instance.selectedDocument;
			var historyCollection:ArrayCollection = currentDocument.history;
			var currentTargetDocument:Application = currentDocument.instance as Application; // should be typed
			var historyLength:int = historyCollection.length;
			var changeIndex:int = getNextHistoryIndex();
			var currentIndex:int = getHistoryIndex();
			var historyEvent:HistoryEventItem;
			var historyItem:HistoryEvent;
			var affectsDocument:Boolean;
			var setStartValues:Boolean;
			var historyEvents:Array;
			var addItems:AddItems;
			var isInvalid:Boolean;
			var eventsLength:int;
			var remove:Boolean;
			var action:String;
			
			
			// need to make sure everything is validated first
			// think about doing the following:
			// LayoutManager.getInstance().usePhasedInstantiation = false;
			// LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid. Needs a fix.") : 0;
			// also use in undo()
			
			// no changes made
			if (!historyLength) {
				return -1;
			}
			
			// cannot redo any more changes
			if (changeIndex==-1 || changeIndex>=historyLength) {
				if (instance.hasEventListener(RadiateEvent.END_OF_UNDO_HISTORY)) {
					instance.dispatchEvent(new RadiateEvent(RadiateEvent.END_OF_UNDO_HISTORY));
				}
				return historyLength-1;
			}
			
			// get current change to be redone
			historyItem = historyCollection.length ? historyCollection.getItemAt(changeIndex) as HistoryEvent : null;
			
			historyEvents = historyItem.historyEventItems;
			eventsLength = historyEvents.length;
			//changes = historyEvents;
			
			for (var j:int;j<eventsLength;j++) {
				historyEvent = HistoryEventItem(historyEvents[j]);
				//changesLength = changes ? changes.length: 0;
				
				addItems = historyEvent.addItemsInstance;
				action = historyEvent.action;
				affectsDocument = dispatchForApplication && historyEvent.targets.indexOf(currentTargetDocument)!=-1;

				
				if (action==RadiateEvent.ADD_ITEM) {
					isInvalid = LayoutManager.getInstance().isInvalid();
					if (isInvalid) {
						LayoutManager.getInstance().validateNow();
						LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 4.") : 0;
					}
					// redo the add
					addItems.apply(addItems.destination as UIComponent);
					historyEvent.reversed = false;
					
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchAddEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
					
				}
				else if (action==RadiateEvent.MOVE_ITEM) {
					// redo the move
					if (addItems) {
						
						// RangeError: Index 2 is out of range. 
						// we must validate
						isInvalid = LayoutManager.getInstance().isInvalid();
						if (isInvalid) {
							LayoutManager.getInstance().validateNow();
							LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 5") : 0;
						}
						
						addItems.apply(addItems.destination as UIComponent);
						historyEvent.reversed = false;
						
						if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
							instance.dispatchMoveEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
						}
					}
					else {
						
						applyChanges(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties, historyEvent.styles,
							setStartValues);
						historyEvent.reversed = false;
						
						if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
							instance.dispatchPropertyChangeEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
						}
					}
					
				}
				else if (action==RadiateEvent.REMOVE_ITEM) {
					
					isInvalid = LayoutManager.getInstance().isInvalid();
					if (isInvalid) {
						LayoutManager.getInstance().validateNow();
						LayoutManager.getInstance().isInvalid() ? Radiate.log.debug("Layout Manager is still invalid at note 6") : 0;
					}
					
					// redo the remove
					addItems.remove(addItems.destination as UIComponent);
					historyEvent.reversed = false;
					remove = true;
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchRemoveItemsEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
				}
				else if (action==RadiateEvent.PROPERTY_CHANGED) {
					applyChanges(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties, historyEvent.styles,
						setStartValues);
					historyEvent.reversed = false;
					
					if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
						instance.dispatchPropertyChangeEvent(historyEvent.targets, [historyEvent.propertyChanges], historyEvent.properties);
					}
				}
			}
			
			
			historyItem.reversed = false;
			
			// select target
			if (selectTargetOnHistoryChange) {
				if (remove) {
					instance.setTargets(currentTargetDocument, true);
				}
				else {
					instance.setTargets(historyEvent.targets, true);
				}
			}
			
			if (eventsLength) {
				historyIndex = getHistoryIndex();
				
				if (dispatchEvents || (dispatchForApplication && affectsDocument)) {
					instance.dispatchHistoryChangeEvent(historyIndex, currentIndex);
				}
				
				return changeIndex;
			}
			
			return historyLength;
		}
		
		/**
		 * Apply changes to targets. You do not call this. Set properties through setProperties method. 
		 * 
		 * @param setStartValues applies the start values rather 
		 * than applying the end values
		 * 
		 * @param property string or array of strings containing the 
		 * names of the properties to set or null if setting styles
		 * 
		 * @param style string or araray of strings containing the 
		 * names of the styles to set or null if setting properties
		 * */
		public static function applyChanges(targets:Array, changes:Array, property:*, style:*, setStartValues:Boolean=false):Boolean {
			var length:int = changes ? changes.length : 0;
			var effect:SetAction = new SetAction();
			var onlyPropertyChanges:Array = [];
			var directApply:Boolean = true;
			var isStyle:Boolean = style && style.length>0;
			
			for (var i:int;i<length;i++) {
				if (changes[i] is PropertyChanges) { 
					onlyPropertyChanges.push(changes[i]);
				}
			}
			
			effect.targets = targets;
			effect.propertyChangesArray = onlyPropertyChanges;
			
			if (isStyle) {
				effect.property = style;
			}
			
			effect.relevantProperties = ArrayUtil.toArray(property);
			effect.relevantStyles = ArrayUtil.toArray(style);
			
			// this works for styles and properties
			// note: the property applyActualDimensions is used to enable width and height values to stick
			if (directApply) {
				effect.applyEndValuesWhenDone = false;
				effect.applyActualDimensions = false;
				
				if (setStartValues) {
					effect.applyStartValues(onlyPropertyChanges, targets);
				}
				else {
					effect.applyEndValues(onlyPropertyChanges, targets);
				}
				
				// Revalidate after applying
				LayoutManager.getInstance().validateNow();
			}
				
				// this works for properties but not styles
				// the style value is restored at the end
			else {
				
				effect.applyEndValuesWhenDone = false;
				effect.play(targets, setStartValues);
				effect.playReversed = false;
				effect.end();
				LayoutManager.getInstance().validateNow();
			}
			
			return true;
		}
		
		/**
		 * Removes properties changes for null or same value targets
		 * @private
		 */
		public static function stripUnchangedValues(propChanges:Array):Array {
			
			// Go through and remove any before/after values that are the same.
			for (var i:int = 0; i < propChanges.length; i++) {
				if (propChanges[i].stripUnchangedValues == false)
					continue;
				
				for (var prop:Object in propChanges[i].start) {
					if ((propChanges[i].start[prop] ==
						propChanges[i].end[prop]) ||
						(typeof(propChanges[i].start[prop]) == "number" &&
							typeof(propChanges[i].end[prop])== "number" &&
							isNaN(propChanges[i].start[prop]) &&
							isNaN(propChanges[i].end[prop])))
					{
						delete propChanges[i].start[prop];
						delete propChanges[i].end[prop];
					}
				}
			}
			
			return propChanges;
		}
		
		
		
		/**
		 * Checks if changes are available. 
		 * */
		public static function changesAvailable(changes:Array):Boolean {
			var length:int = changes.length;
			var changesAvailable:Boolean;
			var item:PropertyChanges;
			var name:String;
			
			for (var i:int;i<length;i++) {
				if (!(changes[i] is PropertyChanges)) continue;
				
				item = changes[i];
				
				for (name in item.start) {
					changesAvailable = true;
					return true;
				}
				
				for (name in item.end) {
					changesAvailable = true;
					return true;
				}
			}
			
			return changesAvailable;
		}
		
		//private static var _historyIndex:int = -1;
		
		/**
		 * Selects the target on undo and redo
		 * */
		public static var selectTargetOnHistoryChange:Boolean = true;
		
		private static var _historyIndex:int = -1;

		/**
		 * Current history index. 
		 * The history index is the index of last applied change. Or
		 * to put it another way the index of the last reversed change minus 1. 
		 * If there are 10 total changes and one has been reversed then 
		 * we would be at the 9th change. The history index would 
		 * be 8 since 9-1 = 8 since the array is a zero based index. 
		 * 
		 * value -1 means no history
		 * value 0 means one item
		 * value 1 means two items
		 * value 2 means three items
		 * */
		[Bindable]
		public static function get historyIndex():int {
			
			return _historyIndex;
			//var document:IDocument = instance.selectedDocument;
			//return document ? document.historyIndex : -1;
		}

		/**
		 * @private
		 */
		public static function set historyIndex(value:int):void {
			var document:IDocument = instance.selectedDocument;
			if (document.historyIndex==value) {
				//
			}
			else {
				document.historyIndex = value;
			}
			
			_historyIndex = value;
			
			var totalItems:int = history ? 
				history.length : 0;
			var hasItems:Boolean = totalItems>0;
			
			// has forward history
			if (hasItems && historyIndex+1<totalItems) {
				canRedo = true;
			}
			else {
				canRedo = false;
			}
			
			// has previous items
			if (hasItems && historyIndex>-1) {
				canUndo = true;
			}
			else {
				canUndo = false;
			}
		}
		
		/**
		 * Indicates if undo is available
		 * */
		[Bindable]
		public static var canUndo:Boolean;
		
		/**
		 * Indicates if redo is available
		 * */
		[Bindable]
		public static var canRedo:Boolean;
		
		/**
		 * Get the index of the next item that can be undone. 
		 * If there are 10 changes and one has been reversed the 
		 * history index would be 8 since 10-1=9-1=8 since the array is 
		 * a zero based index. 
		 * */
		public static function getPreviousHistoryIndex():int {
			var document:IDocument = instance.selectedDocument;
			var length:int = document.history.length;
			var historyItem:HistoryEvent;
			var index:int;
			
			for (var i:int;i<length;i++) {
				historyItem = document.history.getItemAt(i) as HistoryEvent;
				
				if (historyItem.reversed) {
					return i-1;
				}
			}
			
			return length-1;
		}
		
		/**
		 * Get the index of the next item that can be redone in the history array. 
		 * If there are 10 changes and one has been reversed the 
		 * next history index would be 9 since 10-1=9-1=8+1=9 since the array is 
		 * a zero based index. 
		 * */
		public static function getNextHistoryIndex():int {
			var document:IDocument = instance.selectedDocument;
			var length:int = document.history.length;
			var historyItem:HistoryEvent;
			var index:int;
			
			// start at the beginning and find the next item to redo
			for (var i:int;i<length;i++) {
				historyItem = document.history.getItemAt(i) as HistoryEvent;
				
				if (historyItem.reversed) {
					return i;
				}
			}
			
			return length;
		}
		
		/**
		 * Get history index
		 * */
		public static function getHistoryIndex():int {
			var document:IDocument = instance.selectedDocument;
			var length:int = document ? document.history.length : 0;
			var historyItem:HistoryEvent;
			var index:int;
			
			// go through and find last item that is reversed
			for (var i:int;i<length;i++) {
				historyItem = document.history.getItemAt(i) as HistoryEvent;
				
				if (historyItem.reversed) {
					return i-1;
				}
			}
			
			return length-1;
		}
		
		/**
		 * Returns the history event by index
		 * */
		public function getHistoryItemAtIndex(index:int):HistoryEvent {
			var document:IDocument = instance.selectedDocument;
			var length:int = document ? document.history.length : 0;
			var historyItem:HistoryEvent;
			
			// no changes
			if (!length) {
				return null;
			}
			
			// all changes have already been undone
			if (index<0) {
				return null;
			}
			
			// get change 
			historyItem = document.history.length ? document.history.getItemAt(index) as HistoryEvent : null;
			
			return historyItem;
		}

		
		/**
		 * Given a target or targets, property name and value
		 * returns an array of PropertyChange objects.
		 * Points to createPropertyChanges()
		 * 
		 * @see createPropertyChanges()
		 * */
		public static function createPropertyChange(targets:Array, property:String, style:String, value:*, description:String = ""):Array {
			var values:Object = {};
			var changes:Array;
			
			if (property) {
				values[property] = value;
			}
			else if (style) {
				values[style] = value;
			}
			
			changes = createPropertyChanges(targets, ArrayUtil.toArray(property), ArrayUtil.toArray(style), values, description, false);
			
			return changes;
		}
		
		/**
		 * Given a target or targets, properties and value object (name value pair)
		 * returns an array of PropertyChange objects.
		 * Value must be an object containing the properties mentioned in the properties array
		 * */
		public static function createPropertyChanges(targets:Array, properties:Array, styles:Array, value:Object, description:String = "", storeInHistory:Boolean = true):Array {
			var tempEffect:SetAction = new SetAction();
			var propertyChanges:PropertyChanges;
			var changes:Array;
			var propertyOrStyle:String;
			var isStyle:Boolean = styles && styles.length>0;
			
			tempEffect.targets = targets;
			tempEffect.property = isStyle ? styles[0] : properties[0];
			tempEffect.relevantProperties = properties;
			tempEffect.relevantStyles = styles;
			
			// get start values for undo
			changes = tempEffect.captureValues(null, true);
			
			// This may be hanging on to bindable objects
			// set the values to be set to the property 
			// ..later - what??? give an example
			for each (propertyChanges in changes) {
				
				// for properties 
				for each (propertyOrStyle in properties) {
					
					// value may be an object with properties or a string
					// because we accept an object containing the values with 
					// the name of the properties or styles
					if (value && propertyOrStyle in value) {
						propertyChanges.end[propertyOrStyle] = value[propertyOrStyle];
					}
					else {
						propertyChanges.end[propertyOrStyle] = value;
					}
				}
				
				// for styles
				for each (propertyOrStyle in styles) {
					
					// value may be an object with properties or a string
					// because we accept an object containing the values with 
					// the name of the properties or styles
					if (value && propertyOrStyle in value) {
						propertyChanges.end[propertyOrStyle] = value[propertyOrStyle];
					}
					else {
						propertyChanges.end[propertyOrStyle] = value;
					}
				}
			}
			
			// we should move this out
			// add property changes array to the history dictionary
			if (storeInHistory) {
				return createHistoryEvents(targets, changes, properties, styles, value, description);
			}
			
			return [propertyChanges];
		}
		
		private static var _disableHistoryManagement:Boolean;

		/**
		 * Disables history management. We do this when importing documents since
		 * it creates the document 5x faster. 
		 * */
		public static function get disableHistoryManagement():Boolean {
			return _disableHistoryManagement;
		}

		/**
		 * @private
		 */
		[Bindable(event="disableHistoryManagement")]
		public static function set disableHistoryManagement(value:Boolean):void {
			if (_disableHistoryManagement == value) return;
			_disableHistoryManagement = value;
		}

		
		/**
		 * Creates a history event in the history 
		 * Changes can contain a property or style changes or add items 
		 * */
		public static function createHistoryEvents(targets:Array, changes:Array, properties:*, styles:*, value:*, description:String = null, action:String=RadiateEvent.PROPERTY_CHANGED, remove:Boolean = false):Array {
			var factory:ClassFactory = new ClassFactory(HistoryEventItem);
			var historyEvent:HistoryEventItem;
			var events:Array = [];
			var reverseAddItems:AddItems;
			var change:Object;
			var length:int;
			
			if (disableHistoryManagement) return [];
			
			// create property change objects for each
			for (var i:int;i<changes.length;i++) {
				change = changes[i];
				historyEvent 						= factory.newInstance();
				historyEvent.action 				= action;
				historyEvent.targets 				= targets;
				historyEvent.description 			= description;
				
				// check for property change or add display object
				if (change is PropertyChanges) {
					historyEvent.properties 		= ArrayUtil.toArray(properties);
					historyEvent.styles 			= ArrayUtil.toArray(styles);
					historyEvent.propertyChanges 	= PropertyChanges(change);
				}
				else if (change is AddItems && !remove) {
					historyEvent.addItemsInstance 	= AddItems(change);
					length = targets.length;
					
					// trying to add support for multiple targets - it's not all there yet
					// probably not the best place to get the previous values or is it???
					for (var j:int=0;j<length;j++) {
						historyEvent.reverseAddItemsDictionary[targets[j]] = createReverseAddItems(targets[j]);
					}
				}
				else if (change is AddItems && remove) {
					historyEvent.removeItemsInstance 	= AddItems(change);
					length = targets.length;
					
					// trying to add support for multiple targets - it's not all there yet
					// probably not the best place to get the previous values or is it???
					for (j=0;j<length;j++) {
						historyEvent.reverseRemoveItemsDictionary[targets[j]] = createReverseAddItems(targets[j]);
					}
				}
				events[i] = historyEvent;
			}
			
			return events;
			
		}
		
		/**
		 * Creates a remove item from an add item. 
		 * */
		public static function createReverseAddItems(target:Object):AddItems {
			var elementContainer:IVisualElementContainer;
			var position:String = AddItems.LAST;
			var visualElement:IVisualElement;
			var reverseAddItems:AddItems;
			var elementIndex:int = -1;
			var propertyName:String; 
			var destination:Object;
			var description:String;
			var relativeTo:Object; 
			var vectorClass:Class;
			var isStyle:Boolean; 
			var isArray:Boolean; 
			var index:int = -1; 
			
			if (!target) return null;
			
			// create add items with current values we can revert back to
			reverseAddItems = new AddItems();
			reverseAddItems.destination = target.parent;
			reverseAddItems.items = target;
			
			destination = reverseAddItems.destination;
			
			visualElement = target as IVisualElement;
			
			// set default
			if (!position) {
				position = AddItems.LAST;
			}
			
			// Check for non basic layout destination
			// if destination is not a basic layout
			// find the position and set the relative object 
			if (destination is IVisualElementContainer 
				&& destination.numElements>0) {
				elementContainer = destination as IVisualElementContainer;
				index = elementContainer.getElementIndex(visualElement);
				
				
				if (elementContainer is GroupBase 
					&& !(GroupBase(elementContainer).layout is BasicLayout)) {
					

					// add as first item
					if (index==0) {
						position = AddItems.FIRST;
					}
					
					// get relative to object
					else if (index<=elementContainer.numElements) {
						
						
						// if element is already child of container account for remove of element before add
						if (visualElement && visualElement.parent == destination) {
							elementIndex = destination.getElementIndex(visualElement);
							index = elementIndex < index ? index-1: index;
							
							if (index<=0) {
								position = AddItems.FIRST;
							}
							else {
								relativeTo = destination.getElementAt(index-1);
								position = AddItems.AFTER;
							}
						}
							// add as last item
						else if (index>=destination.numElements) {
							position = AddItems.LAST;
						}
							// add after first item
						else if (index>0) {
							relativeTo = destination.getElementAt(index-1);
							position = AddItems.AFTER;
						}
					}
				}
			}
			
			
			reverseAddItems.destination = destination;
			reverseAddItems.position = position;
			reverseAddItems.relativeTo = relativeTo;
			reverseAddItems.propertyName = propertyName;
			reverseAddItems.isArray = isArray;
			reverseAddItems.isStyle = isStyle;
			reverseAddItems.vectorClass = vectorClass;
			
			return reverseAddItems;
		}
		
		/**
		 * Stores a history event in the history events dictionary
		 * Changes can contain a property changes object or add items object
		 * */
		public static function removeHistoryEvent(changes:Array):void {
			var historyEvent:HistoryEventItem;
			var change:Object;
			
			// delete change objects
			for each (change in changes) {
				historyEventsDictionary[change] = null;
				delete historyEventsDictionary[change];
			}
			
		}
		
		/**
		 * Adds property change items to the history array
		 * */
		public static function addHistoryItem(historyEventItem:HistoryEventItem, description:String = null):void {
			addHistoryEvents(ArrayUtil.toArray(historyEventItem), description);
		}
		
		/**
		 * Adds property change items to the history array
		 * */
		public static function addHistoryEvents(historyEvents:Array, description:String = null):void {
			var document:IDocument = instance.selectedDocument;
			var historyEvent:HistoryEvent;
			var currentIndex:int = getHistoryIndex();
			var length:int = document ? document.history.length : 0;
			var historyTargets:Array;
			
			if (disableHistoryManagement) return;
			
			history.disableAutoUpdate();
			
			// trim history 
			if (currentIndex!=length-1) {
				for (var i:int = length-1;i>currentIndex;i--) {
					historyEvent = document.history.removeItemAt(i) as HistoryEvent;
					historyEvent.purge();
				}
			}
			
			historyEvent = new HistoryEvent();
			historyEvent.description = description ? HistoryEventItem(historyEvents[0]).description : description;
			historyEvent.historyEventItems = historyEvents;
			
			// we should remember to remove these references when truncating history
			for (i=0;i<historyEvents.length;i++) {
				historyTargets = HistoryEventItem(historyEvents[i]).targets;
				for (var j:int=0;j<historyTargets.length;j++) {
					if (historyEvent.targets.indexOf(historyTargets[j])==-1) {
						historyEvent.targets.push(historyTargets[j]);
					}
				}
			}
			
			document.history.addItem(historyEvent);
			document.historyIndex = getHistoryIndex();
			document.history.enableAutoUpdate();
			
			document.historyIndex = getHistoryIndex();
			
			historyIndex = getHistoryIndex();
			
			instance.dispatchHistoryChangeEvent(currentIndex+1, currentIndex);
		}
		
		/**
		 * Removes property change items in the history array
		 * */
		public static function removeHistoryItem(changes:Array):void {
			var document:IDocument = instance.selectedDocument;
			var currentIndex:int = getHistoryIndex();
			
			var itemIndex:int = document.history.getItemIndex(changes);
			
			if (itemIndex>0) {
				document.history.removeItemAt(itemIndex);
			}
			
			document.historyIndex = getHistoryIndex();
			historyIndex = getHistoryIndex();
			
			instance.dispatchHistoryChangeEvent(currentIndex-1, currentIndex);
		}
		
		/**
		 * Removes all history in the history array. 
		 * Note: We should set the changes to null. 
		 * */
		public static function removeAllHistory():void {
			var document:IDocument = instance.selectedDocument;
			var currentIndex:int = getHistoryIndex();
			document.history.removeAll();
			document.history.refresh(); // we should loop through and run purge on each HistoryItem
			instance.dispatchHistoryChangeEvent(-1, currentIndex);
		}
		
		/**
		 * Returns true if two objects are of the same class type
		 * */
		public function isSameClassType(target:Object, target1:Object):Boolean {
			return ClassUtils.isSameClassType(target, target1);
		}
	}
}

class SINGLEDOUBLE{}