////////////////////////////////////////////////////////////////////////////////
//
//  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.utils {
	import com.flexcapacitor.events.InspectorEvent;
	import com.flexcapacitor.graphics.LayoutLines;
	import com.flexcapacitor.model.AccessorMetaData;
	import com.flexcapacitor.model.MetaData;
	import com.flexcapacitor.model.StyleMetaData;
	import com.flexcapacitor.model.VisualElementVO;
	
	import flash.desktop.Clipboard;
	import flash.desktop.ClipboardFormats;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.IEventDispatcher;
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getQualifiedSuperclassName;
	
	import mx.collections.ArrayCollection;
	import mx.collections.XMLListCollection;
	import mx.core.IVisualElement;
	import mx.core.IVisualElementContainer;
	import mx.core.UIComponent;
	import mx.managers.ISystemManager;
	import mx.utils.DescribeTypeCache;
	import mx.utils.DescribeTypeCacheRecord;
	import mx.utils.NameUtil;
	import mx.utils.ObjectUtil;
	
	import avmplus.DescribeType;

	public class ClassUtils {


		public function ClassUtils() {


		}
		
		/**
		 * @copy NameUtil.getUnqualifiedClassName()
		 * */
		public static function getClassName(element:Object):String {
			var name:String = NameUtil.getUnqualifiedClassName(element);
			return name;
		}
		
		/**
		 * Get unqualified class name of the target object. <br/>
		 * 
		 * If target has the id of myImage and include class name is true then the result is
		 * "Image.myImage". If delimiter is "_" then the result is "Image_myImage". 
		 * If includeClassName is false then the result is, "myImage". 
		 * */
		public static function getClassNameOrID(element:Object, includeClassName:Boolean = false, delimiter:String = "."):String {
			var name:String = NameUtil.getUnqualifiedClassName(element);
			var id:String = element && "id" in element ? element.id : null;
			
			return !id ? name : includeClassName ? name + "." + id : id;
		}
		
		/**
		 * Get unqualified class name of the document of the target object
		 * returns null if element is not a UIComponent
		 * */
		public static function getDocumentName(element:Object):String {
			var name:String;
			if (element is UIComponent) {
				name = NameUtil.getUnqualifiedClassName(UIComponent(element).document);
			}
			return name;
		}
		
		/**
		 * Get the type of the value passed in
		 * */
		public static function getValueType(value:*):String {
			var type:String = getQualifiedClassName(value);
			
			if (type=="int") {
				if (typeof value=="number") {
					type = "Number";
				}
			}
			
			return type;
		}
		
		/**
		 * Get fully qualified package of an object minus the class name. 
		 * 
		 * For example, if fully qualified class name is "mx.components::Button" then
		 * this method returns "mx.components".
		 * */
		public static function getPackageName(element:Object):String {
			var name:String = flash.utils.getQualifiedClassName(element);
			if (name && name.indexOf("::")) {
				name = name.split("::")[0];
			}
			
			return name;
		}

		/**
		 * Get super class name of the target object
		 * */
		public static function getSuperClassName(element:Object):String {
			var name:String = flash.utils.getQualifiedSuperclassName(element);
			if (name && name.indexOf("::")) {
				name = name.split("::")[name.split("::").length-1]; // i'm sure theres a better way to do this
			}
			
			return name;
		}

		/**
		 * Get the package of the super class name of the target
		 * */
		public static function getSuperClassPackage(element:Object):String {
			var name:String = flash.utils.getQualifiedSuperclassName(element);
			if (name && name.indexOf("::")) {
				name = name.split("::")[0];
			}
			
			return name;
		}


		/**
		 * Gets the ID of the target object
		 * 
		 * @param name if id is not available then if true then use name
		 * @param className if id is not available then if true use class name
		 * 
		 * returns id or name or class name or null if no ID is specified
		 * */
		public static function getIdentifierOrName(element:Object, name:Boolean = false, className:Boolean = false):String {

			if (element && "id" in element && element.id) {
				return element.id;
			}
			else if (element && name && "name" in element && element.name) {
				return element.name;
			}
			else if (element && className) {
				return getClassName(element);
			}
			
			return null;
		}

		/**
		 * Get name of target object or null if not available
		 * */
		public static function getName(element:Object):String {
			var name:String;

			if (element.hasOwnProperty("name") && element.name) {
				name = element.name;
			}

			return name;
		}

		/**
		 * Get qualified class name of the target object. 
		 * If normalize is true then replaces, "::" with ".";
		 * 
		 * @copy flash.utils.getQualifiedClassName()
		 * */
		public static function getQualifiedClassName(element:Object, normalize:Boolean = false):String {
			var name:String = flash.utils.getQualifiedClassName(element);
			if (normalize && name) {
				name = name.replace("::", ".");
			}
			return name;
		}

		/**
		 * Checks if the source object is the same type as the target object. 
		 * */
		public static function isSameClassType(source:Object, target:Object):Boolean {
			if (source==null && target!=null) {
				return false;
			}
			if (target==null && source!=null) {
				return false;
			}
			
			if (flash.utils.getQualifiedClassName(source) == flash.utils.getQualifiedClassName(target)) {
				return true;
			}
			
			return false;
		}

		/**
		 * With the given target it returns a regexp pattern to find the exact instance in MXML
		 * If isScript is true it attempts to returns a pattern to find the exact instance in AS3
		 * The MXML pattern will find the instance with that ID. If the instance doesn't have an ID it no worky.
		 * NOTE: Press CMD+SHIFT+F to and check regular expression in the Find in Files dialog
		 * */
		public static function getRegExpSearchPattern(target:DisplayObject, isScript:Boolean = false):String {
			var id:String = getIdentifierOrName(target);
			var className:String = NameUtil.getUnqualifiedClassName(target);
			var pattern:String;
			var scriptPattern:String;

			if (id == null) {
				pattern = className + "(.*)";
			}
			else {
				pattern = className + "(.*)id\\s?=\\s?[\"|']" + id + "[\"|']";
				scriptPattern = id + ".addEventListener";
			}


			if (isScript) {
				return scriptPattern;
			}

			return pattern;
		}

		
		/**
		 * Clears outline drawn around target display object
		 * */
		public static function clearSelection(target:Object, systemManager:ISystemManager, remove:Boolean = false):void {
			LayoutLines.getInstance().clear(target, systemManager, remove);
		}
		
		/**
		 * Draws outline around target display object
		 * */
		public static function drawSelection(target:Object, systemManager:ISystemManager):void {
			LayoutLines.getInstance().drawLines(target, systemManager);
		}

		/**
		 * Copy text to clipboard
		 * */
		public static function copyToClipboard(text:String, format:String=ClipboardFormats.TEXT_FORMAT):void {
			Clipboard.generalClipboard.setData(ClipboardFormats.TEXT_FORMAT, text);
		}

		/**
		 * Returns an array of display objects of type VisualElementVO
		 * Optionally returns elements
		 * */
		public static function getElementChildrenArray(displayObject:DisplayObject, getElements:Boolean = false, getSkins:Boolean = true):ArrayCollection {
			var displayObject:DisplayObject = DisplayObject(displayObject);
			var displayObjectContainer:DisplayObjectContainer;

			var visualElementContainer:IVisualElementContainer;
			var visualElement:IVisualElement;

			var visualElementVO:VisualElementVO = new VisualElementVO();

			var children:ArrayCollection = new ArrayCollection();


			// attempt to cast to a specific type and assign in the process
			displayObjectContainer = displayObject as DisplayObjectContainer;
			visualElementContainer = displayObject as IVisualElementContainer;
			visualElement = displayObject as IVisualElement;


			// gather all the display objects on the current display object
			if (displayObjectContainer) {

				for (var bb:int = 0; bb < displayObjectContainer.numChildren; bb++) {
					
						// visualElementVO = createDisplayObjectVO(displayObjectContainer.getChildAt(bb));
					visualElementVO = VisualElementVO.unmarshall(displayObjectContainer.getChildAt(bb));
					children.addItem(visualElementVO);
				}
			}

			if (visualElementContainer && getElements) {

				for (var cc:int = 0; cc < visualElementContainer.numElements; cc++) {
						//visualElementVO = createDisplayObjectVO(displayObjectContainer.getChildAt(cc));
					visualElementVO = VisualElementVO.unmarshall(DisplayObject(visualElementContainer.getElementAt(cc)));
					children.addItem(visualElementVO);
				}
			}

			return children;
		}

		/**
		 * Get ancestors of target 
		 * 
		 * @param target
		 * @param collection
		 * @param ancestors
		 * @return
		 */
		public static function getVisualElementsArray(target:DisplayObject, collection:Array, ancestors:int = 0):Array {
			var vo:VisualElementVO;


			// do the worm up the display list
			while (target && ancestors>-1) {

				// store display element information
				vo = VisualElementVO.unmarshall(target);

				// save reference to display element VO's for tree
				if (!collection) collection = new Array();
				collection.push(vo);

				target = target.parent;
				ancestors--;

			}

			return collection;
		}
		
		/**
		 * Get the parent of the target that is also a UIComponent
		 * 
		 * @return
		 */
		public static function getParentUIComponent(target:DisplayObject):UIComponent {
			var found:Boolean;
			
			// run up the display list
			while (target) {
				target = target.parent;
				
				// check if next parent exists
				if (!target) {
					break;
				}
				
				if (target is UIComponent) {
					found = true;
					break;
				}
				
			}
			
			if (found) return UIComponent(target);
			return null;
		}
		
		/**
		 * Get the name of the target parent that is also a UIComponent
		 * 
		 * @return
		 */
		public static function getParentUIComponentName(target:DisplayObject):String {
			var parent:DisplayObject = getParentUIComponent(target);
			var className:String = getClassName(parent);
			return className;
		}
		
		
		/**
		 * Get parent document name
		 * 
		 * @return null if target is not a UIComponent
		 */
		public static function getParentDocumentName(target:Object):String {
			var className:String;
			if (target is UIComponent) {
				className = getClassName(target.parentDocument);
			}
			return className;
		}
		
		
		/**
		 * Get parent document name
		 * 
		 * @return
		 */
		public static function getClassNameAndPackage(target:Object):Array {
			var className:String;
			var classPath:String;
			
			className = getClassName(target);
			classPath = getPackageName(target);
			
			return [className, classPath];
		}
		
		
		/**
		 * Dispatch target change event
		 * 
		 * @return
		 */
		public static function dispatchTargetChangeEvent(target:Object, source:IEventDispatcher):void {
			
			// let other inspectors know there is a new target selected
			var selectionChangeEvent:InspectorEvent = new InspectorEvent(InspectorEvent.CHANGE);
			selectionChangeEvent.targetItem = target;
			
			// store previous targets in a dictionary
			
			if (source) {
				source.dispatchEvent(selectionChangeEvent);
			}			
		}
		
		
		/**
		 * Change target. Use this instead of dispatchTargetChangeEvent()
		 * 
		 * TODO: Add a weak reference to the old target in a static array for history type navigation
		 * 
		 * @return
		 */
		public static function updateTarget(target:Object, source:IEventDispatcher):void {
			// TODO: Add a weak reference to the old target in a static array for history type navigation
			
			// let other inspectors know there is a new target selected
			var selectionChangeEvent:InspectorEvent = new InspectorEvent(InspectorEvent.CHANGE);
			selectionChangeEvent.targetItem = target;
			
			if (source) {
				source.dispatchEvent(selectionChangeEvent);
			}			
		}
		
		/**
		 * Converts an integer to hexidecimal. 
		 * For example, 16117809 returns "#EEEEEE" or something
		 * @return
		 */
		public static function convertIntToHex(item:Object):String {
			var hex:String = Number(item).toString(16);
			return ("00000" + hex.toUpperCase()).substr(-6);
		}
		
		/**
		 * Get describeType data for the given class. 
		 * Can take string, instance or class. 
		 * */
		public static function getDescribeType(object:Object):XML {
			var describedTypeRecord:mx.utils.DescribeTypeCacheRecord = mx.utils.DescribeTypeCache.describeType(object);
			
			return describedTypeRecord.typeDescription;
		}
		
		/**
		 * Get AccessorMetaData data for the given property. 
		 * */
		public static function getMetaDataOfProperty(target:Object, property:String):AccessorMetaData {
			var describedTypeRecord:mx.utils.DescribeTypeCacheRecord = mx.utils.DescribeTypeCache.describeType(target);
			var accessorMetaData:AccessorMetaData = new AccessorMetaData();
			var matches:XMLList = describedTypeRecord.typeDescription.accessor.(@name==property);
			var node:XML;
			
			if (matches.length()>0) {
				node = matches[0];
				accessorMetaData.unmarshall(node, target);
				return accessorMetaData;
			}
			
			return null;
		}
		
		/**
		 * Get StyleMetaData data for the given style. 
		 * */
		public static function getMetaDataOfStyle(target:Object, style:String, superType:String = null):StyleMetaData {
			var describedTypeRecord:mx.utils.DescribeTypeCacheRecord;
			var matches:XMLList;
			var styleMetaData:StyleMetaData;
			var extendsClassList:XMLList;
			var node:XML;
			
			if (superType) {
				describedTypeRecord = mx.utils.DescribeTypeCache.describeType(superType);
			}
			else {
				describedTypeRecord = mx.utils.DescribeTypeCache.describeType(target);
			}
			
			if (superType || target is String) {
				matches = describedTypeRecord.typeDescription.factory.metadata.(@name=="Style").arg.(@value==style);
			}
			else if (target is Object) {
				matches = describedTypeRecord.typeDescription.metadata.(@name=="Style").arg.(@value==style);
			}
			
			if (matches && matches.length()==0) {
				
				if (superType || target is String) {
					extendsClassList = describedTypeRecord.typeDescription.factory.extendsClass;
				}
				else if (target is Object) {
					extendsClassList = describedTypeRecord.typeDescription.extendsClass;
				}
				
				var length:int = extendsClassList.length();
				
				for (var i:int;i<length;i++) {
					var type:String = extendsClassList[i].@type;
					if (type=="Class") return null;
					return getMetaDataOfStyle(target, style, type);
				}
				
			}
			
			if (matches.length()>0) {
				node = matches[0].parent();
				styleMetaData = new StyleMetaData();
				styleMetaData.unmarshall(node, target);
				return styleMetaData;
			}
			
			return null;
		}
		
		/**
		 * Creates an array of metadata items for the given object type including inherited metadata. 
		 * 
		 * For example, if you give it a Spark Button class it gets all the
		 * information for it and then gets it's super class ButtonBase and 
		 * adds all that information and so on until it gets to Object. <br/><br/>
		 * 
		 * Usage:<br/><pre>
		 * var allStyles:XMLList = concatenateMetaDataXMLItems(myButton, "Style", new XMLList());
		 * </pre>
		 * @param metaType The name of the data in the item name property. Either Style or Event
		 * @param existingItems The list of the data in the item name property
		 * */
		public static function concatenateMetaDataXMLItems(object:Object, metaType:String, existingItems:XMLList = null):XMLList {
			var describedTypeRecord:mx.utils.DescribeTypeCacheRecord = mx.utils.DescribeTypeCache.describeType(object);
			var typeDescription:* = describedTypeRecord.typeDescription;
			var hasFactory:Boolean = typeDescription.factory.length()>0;
			var factory:* = typeDescription.factory;
			var extendsClass:XMLList = typeDescription.extendsClass;
			var extendsLength:int = extendsClass.length();
			var list:XMLListCollection = new XMLListCollection(typeDescription.*);
			// can be on typeDescription.metadata or factory.metadata
			var isRoot:Boolean = object is String ? false : true;
			var className:String = !isRoot ? object as String : getQualifiedClassName(object);
			var itemsLength:int;
			var itemsList:XMLList;
			var existingItemsLength:int = existingItems ? existingItems.length() : 0;
			var metaName:String;
			var duplicateItems:Array = [];
			
			if (metaType.toLowerCase()=="style") {
				metaType = "Style"; 
			}
			else if (metaType.toLowerCase()=="event") {
				metaType = "Event"; 
			}
			
			if (hasFactory) {
				//itemsList = factory.metadata.(@name==name); property "name" won't work! no matches found
				itemsList = factory.metadata.(@name==metaType);
			}
			else {
				itemsList = typeDescription.metadata.(@name==metaType);
			}
			
			itemsList = itemsList.copy();
			itemsLength = itemsList.length();
			
			//trace("getting info on class : " + className + " for data on " + nAmEe );
			//trace(" items : " + itemsList);
			
			
			for (var i:int;i<itemsLength;i++) {
				var item:XML = XML(itemsList[i]);
				metaName = item.arg[0].@value;
				item.@name = metaName;
				item.@metadataType = metaType;
				item.@declaredBy = className;
				//item.@className = className.indexOf("::")!=-1 ? className.split("::")[1] : className;
				//continue;
				
				for (var j:int=0;j<existingItemsLength;j++) {
					var existingItem:XML = existingItems[j];
					
					if (metaName==existingItem.@name) {
						delete itemsList[i];
						itemsLength--;
						i--;
						//trace("meta name: " + metaName);
						//trace("Deleting style: " + existingItem.@name);
						continue;
					}
				}
			}
			
			
			if (itemsLength>0) {
				existingItems = new XMLList(existingItems.toString()+itemsList.toString());
			}

			if (isRoot && extendsLength>0) {
				for (i=0;i<extendsLength;i++) {
					var newClass:String = String(extendsClass[i].@type);
					existingItems = concatenateMetaDataXMLItems(newClass, metaType, existingItems);
				}
			}
			
			return existingItems;
		}
		
		
		/**
		 * Sets the property on the target. Supports styles. 
		 * We should probably switch to the set property method 
		 * @return
		 */
		public static function setTargetProperty(target:Object, property:String, value:*, type:String = "String", isPropertyStyle:Object=null):void {
			var newAssignedValue:* = TypeUtils.getTypedValue(value, type);
			TypeUtils.applyProperty(target, property, newAssignedValue, type, isPropertyStyle);
		}
		
			
		/**
		 * @copy spark.components.gridClasses.GridItemEditor#save();
		 */
		public static function setProperty(target:Object, field:String, value:*):Boolean {
			
			var newData:Object = value;
			var property:String = field;
			var data:Object = target;
			var typeInfo:String = "";
			
			for each(var variable:XML in describeType((data).variable)) {
				if (property == variable.@name.toString()) {
					typeInfo = variable.@type.toString();
					break;
				}
			}
			
			if (typeInfo == "String") {
				if (!(newData is String))
					newData = newData.toString();
			}
			else if (typeInfo == "uint") {
				if (!(newData is uint))
					newData = uint(newData);
			}
			else if (typeInfo == "int") {
				if (!(newData is int))
					newData = int(newData);
			}
			else if (typeInfo == "Number") {
				if (!(newData is Number))
					newData = Number(newData);
			}
			else if (typeInfo == "Boolean") {
				if (!(newData is Boolean)) {
					var strNewData:String = newData.toString();
					
					if (strNewData) {
						newData = (strNewData.toLowerCase() == "true") ? true : false;
					}
				}
			}
			
			if (property && data[property] !== newData) {
				data[property] = newData;
			}
			
			return true;
		}
		
		/**
		 *  Returns <code>true</code> if the object reference specified
		 *  is a simple data type. The simple data types include the following:
		 *  <ul>
		 *    <li><code>String</code></li>
		 *    <li><code>Number</code></li>
		 *    <li><code>uint</code></li>
		 *    <li><code>int</code></li>
		 *    <li><code>Boolean</code></li>
		 *    <li><code>Date</code></li>
		 *    <li><code>Array</code></li>
		 *  </ul>
		 *
		 *  @param value Object inspected.
		 *
		 *  @return <code>true</code> if the object specified
		 *  is one of the types above; <code>false</code> otherwise.
		 *  */
		public static function isSimple(value:*):Boolean {
			return ObjectUtil.isSimple(value);
		}
	}
}