<?xml version="1.0" encoding="utf-8"?>
<!--

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.

-->
<s:Group xmlns:controls="com.flexcapacitor.graphics.*"
		 xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 minWidth="40"
		 minHeight="20" 
		 creationComplete="group1_creationCompleteHandler(event)" 
		 xmlns:filters="com.flexcapacitor.filters.*">


	<fx:Script>
		<![CDATA[
			import com.flexcapacitor.controller.Radiate;
			import com.flexcapacitor.events.RadiateEvent;
			import com.flexcapacitor.utils.ClassUtils;
			import com.flexcapacitor.utils.DisplayObjectUtils;
			import com.flexcapacitor.utils.supportClasses.ComponentDescription;
			
			import mx.collections.ArrayCollection;
			import mx.core.UIComponent;
			import mx.events.FlexEvent;
			import mx.utils.NameUtil;
			
			import spark.components.Group;
			
			
			public var backgroundFillAlpha:Number = 0;
			public var backgroundFillColor:uint = 0x000000;
			public var lineAlpha:Number = .8;
			public var lineColor:uint = 0x00FF00;
			public var horizontalOffset:int = -5;
			public var verticalOffset:int = -5;
			public var lineThickness:int = 1;
			public var group:Group;
			
			public var radiate:Radiate;

			[Bindable]
			public var dataProviderList:ArrayCollection = new ArrayCollection();

			public var mouseCurrentTarget:DisplayObject;

			public var mouseTarget:DisplayObject;

			[Bindable]
			public var itemDescription:String;
			
			[Bindable]
			public var parentDocumentName:String;

			private var _stage:Stage;

			private var _target:Object;

			/**
			 * This prevents the click event from ever reaching the target
			 * It may be causing an I beam after clicking on text controls - remove mouse up listener?
			 * */
			public function cancelMouseEvent(target:Object):void {
				DisplayObject(target).addEventListener(MouseEvent.CLICK, cancelClickEvent, false, 10000);
				DisplayObject(target).addEventListener(MouseEvent.MOUSE_UP, cancelMouseUpEvent, false, 10000);
			}
			
			public function cancelClickEvent(e:MouseEvent):void {
				e.preventDefault();
				e.stopPropagation();
				e.stopImmediatePropagation();
				e.target.removeEventListener(MouseEvent.CLICK, cancelClickEvent);
			}
			
			public function cancelMouseUpEvent(e:MouseEvent):void {
				e.preventDefault();
				e.stopPropagation();
				e.stopImmediatePropagation();
				e.target.removeEventListener(MouseEvent.MOUSE_UP, cancelMouseUpEvent);
			}

			/**
			 * WTF am I doing here?
			 * */
			public function findClickHandler(event:MouseEvent):void {
				InteractiveObject(event.target).removeEventListener(MouseEvent.CLICK, findClickHandler, false);
			}

			/**
			 * Gets the ID of the target Object
			 * If no ID is specified returns null
			 * */
			public function getIdentifier(element:Object):String {
				var id:String;

				if (element is UIComponent && element.id) {
					id = UIComponent(element).id;
				}
				else if (element.hasOwnProperty("id") && element.id) {
					id = element.id;
				}
				return id;
			}

			/**
			 * If the target is a display object we get the unqualified class name and if available the ID
			 * If the target is an object we get the unqualified class name only
			 * level is the number of parents to get
			 * */
			public function getItemDescription(targetObject:Object, level:int = 0, description:String = ""):String {

				if (targetObject is DisplayObject) {
					var name:String = NameUtil.displayObjectToString(DisplayObject(targetObject));
					if (name == null) {
						return description != "" ? NameUtil.getUnqualifiedClassName(targetObject) + "\n" + description : NameUtil.getUnqualifiedClassName(targetObject);
					}
					var nameArray:Array = (name.length > 0) ? name.split(".") : [ "undefined" ];
					var id:String = nameArray.pop();
					var className:String = NameUtil.getUnqualifiedClassName(targetObject);
					className = id ? className + " (" + id + ")" : className;

					if (level > 0 && targetObject.parent) {
						description = description != "" ? className + "\n" + description : className;
						description = getItemDescription(targetObject.parent, --level, description);
					}
					else {
						description = description != "" ? className + "\n" + description : className;
					}

					return description;
				}
				else {
					return NameUtil.getUnqualifiedClassName(targetObject);
				}
			}

			public function get target():* {
				return _target;
			}

			/**
			 * This is set automatically when a new target is selected
			 * This can be any type. You must disable this component if the
			 * type is not what you can process.
			 * */
			[Bindable]
			public function set target(value:*):void {

				// the target 
				if (value == null) {
					_target = null;
					
					if (label) {
						label.text = "";
					}
					return;
				}

				_target = value;
				
			}
			
			protected var displayList:ComponentDescription;
			
			protected function findButtonHandler(event:MouseEvent):void {
				_stage = systemManager.stage;
				displayList = DisplayObjectUtils.getComponentDisplayList2(mainDocument);
				addMouseHandlers();
				clearSelection(target, true);
				selectButton.filters = selectFiltersOn;
				systemManager.deployMouseShields(true);
			}

			protected function clearButtonHandler(event:MouseEvent):void {
				_stage = systemManager.stage;
				removeMouseHandlers();
				clearSelection(target, true);
			}

			protected function cancelButtonHandler(event:MouseEvent):void {
				removeMouseHandlers();
				clearSelection(target, true);
				radiate.dispatchTargetClearEvent();
				target = null;
				label.text = "";
			}

			private function addMouseHandlers():void {
				// I don't know how to create a handler that will cancel the event to a button underneath
				// possibly look at code in FlexibleWindow
				// possibly use system managers mouse shield???
				// or Drag manager
				// 
				_stage.addEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseCapture, true, 10000);
				//_stage.addEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseCapturePriority, true, 10000);
				_stage.addEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseBubble, false, 10000);
				_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true, 10000);
				_stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, 10000);
			}

			private function clearSelection(target:Object, remove:Boolean = false):void {
				ClassUtils.clearSelection(target, systemManager);
			}

			private function drawSelection(target:DisplayObject):void {
				ClassUtils.drawSelection(target, systemManager);
			}

			private function getItemUnderMouseBubble(event:MouseEvent):void {
				itemDescription = getItemDescription(event.target, 2);
			}

			private function getItemUnderMouseCapture(event:MouseEvent):void {
				// we need the target to be draggable if we want to allow move
				var isDraggable:Boolean = event.target as Sprite;
				var isParentDraggable:Boolean = (event.target.parent != null && event.target.parent is Sprite);

				mouseTarget = DisplayObject(event.target);
				mouseCurrentTarget = DisplayObject(event.currentTarget);
				
				/* if (mouseTarget.width != 0) {
					// we need to draw on objects parented by the system manager
					drawSelection(mouseTarget);
					label.text = ClassUtils.getClassName(mouseTarget);
				} */
				var point:Point = new Point(event.stageX, event.stageY);
				var objects:Array = stage.getObjectsUnderPoint(point);
				var length:int = objects.length;
				var object:Object;
				var description:ComponentDescription;
				
				
				
				// loop through items under point until we find one on the *component* tree
				for (var i:int;i<length;i++) {
					object = objects[i];
					
					description = DisplayObjectUtils.getTargetInComponentDisplayList(object, displayList);
					if (description) {
						trace("found " + NameUtil.getUnqualifiedClassName(object));
						break;
					}
				}
				
				if (description) {
					// we need to draw on objects parented by the system manager
					drawSelection(description.instance as DisplayObject);
					label.text = description.className;
				}
				
				/* itemDescription = getItemDescription(mouseTarget, 2);
				displayItems = InspectorUtils.getVisualElementsArray(DisplayObject(mouseTarget), displayItems, 2);
				displayItems.reverse();
				dataProviderList.source = displayItems;
				dataProviderList.refresh(); */
			}

			private function getItemUnderMouseCapturePriority(event:MouseEvent):void {
				var itemDescription:String;
			}

			private function mouseUpHandler(event:MouseEvent):void {
				var isDraggable:Boolean = event.target as Sprite;
				var isParentDraggable:Boolean = (event.target.parent != null && event.target.parent is Sprite);

				clearSelection(target, true);

				// this prevents the click event from ever reaching the target
				// this isn't working sometimes for some reason. it used to work.
				cancelMouseEvent(event.target);

				InteractiveObject(event.target).addEventListener(MouseEvent.CLICK, findClickHandler, false, 1000, true);
				
				radiate.dispatchTargetChangeEvent(event.target);

				removeMouseHandlers();
				
				selectButton.filters = selectFiltersOff;
				
				systemManager.deployMouseShields(false);
			}


			private function removeMouseHandlers():void {
				if (_stage==null) return;
				_stage.removeEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseCapture, true);
				//_stage.removeEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseCapturePriority, true);
				_stage.removeEventListener(MouseEvent.MOUSE_MOVE, getItemUnderMouseBubble);
				_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
				_stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
			}
			
			/**
			 * 
			 * */
			public function close():void {
				clearSelection(target, true);
				label.text = "";
				target = null;
			}

			protected function group1_creationCompleteHandler(event:FlexEvent):void {
				radiate.addEventListener(RadiateEvent.TARGET_CHANGE, targetChangeHandler);
				radiate.addEventListener(RadiateEvent.DOCUMENT_CHANGE, documentChangeHandler);
			}
			
			protected function targetChangeHandler(event:RadiateEvent):void {
				target = event.selectedItem;
				label.text = ClassUtils.getClassName(target);
			}
			
			protected function documentChangeHandler(event:RadiateEvent):void {
				mainDocument = event.selectedItem;
				
			}
			public var mainDocument:Object;
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<fx:Array id="selectFiltersOn">
			<filters:BlackAndWhiteFilter />
			<s:DropShadowFilter distance="1" blurX="3" blurY="3" strength=".8" inner="true" knockout="false"/>
		</fx:Array>
		<fx:Array id="selectFiltersOff">
			<filters:BlackAndWhiteFilter />
			<s:DropShadowFilter distance="1" blurX="2" blurY="2" strength=".4" knockout="false"/>
		</fx:Array>
	</fx:Declarations>

	
	<s:HGroup gap="10" width="100%" verticalAlign="middle">
		
		<s:Image id="selectButton" x="14" y="14" 
				 width="18" height="18" 
				 horizontalAlign="center" 
				 scaleMode="letterbox"
				 smooth="true" 
				 source="{Radii8LibraryAssets.selection}" 
				 toolTip="Find Element"
				 filters="{selectFiltersOff}"
				 click="findButtonHandler(event)"
				 verticalAlign="middle"/>
		
		<s:Image x="14" y="14" 
				 width="18" height="18" 
				 horizontalAlign="center" 
				 scaleMode="letterbox"
				 smooth="true" 
				 filters="{selectFiltersOff}"
				 source="{Radii8LibraryAssets.selection}" 
				 toolTip="Hide selection outline"
				 click="clearButtonHandler(event)" 
				 alpha=".5" 
				 verticalAlign="middle"
				 includeInLayout="false"
				 visible="false"/>
		
		<s:Image x="14" y="14" 
				 width="16" height="16" 
				 horizontalAlign="center" 
				 scaleMode="letterbox"
				 smooth="true" 
				 filters="{selectFiltersOff}"
				 source="{Radii8LibraryAssets.cancel}" 
				 toolTip="Cancel Selection"
				 click="cancelButtonHandler(event)" 
				 alpha="1" 
				 enabled="{target}"
				 verticalAlign="middle">
		</s:Image>
		
		<s:Label id="label" color="#444444" />
		
	</s:HGroup>
	

</s:Group>
