 import mx.managers.dragClasses.DragProxy;
 import mx.styles.CSSStyleDeclaration;
 import mx.styles.StyleManager;
-import mx.core.IFlexModuleFactory;
 
 use namespace mx_internal;
 

					dataFetcher.format = format;
						
					dragSource.addHandler(dataFetcher.getClipboardData, format);	
                }
            }
        } 
        if (event.type == NativeDragEvent.NATIVE_DRAG_DROP)
            _relatedObject = event.target as InteractiveObject;
        


        // Need a dragInitiator in NativeDragEvent
        var dragEvent:DragEvent 
            = new DragEvent(newType, false, event.cancelable, 
                            NativeDragManager.dragInitiator as IUIComponent, 
                            dragSource, event.dropAction, ctrlKey, 
                            event.altKey, event.shiftKey);
        dragEvent.buttonDown = event.buttonDown;
        dragEvent.delta = event.delta;
        dragEvent.localX = event.localX;
        dragEvent.localY = event.localY;
        if (newType == DragEvent.DRAG_COMPLETE)
            dragEvent.relatedObject = _relatedObject;
        else
            dragEvent.relatedObject = event.relatedObject;
            
        if (dragAutomationHandlerClass)
		{
			if (newType == DragEvent.DRAG_DROP)
			{
				dragAutomationHandlerClass["recordAutomatableDragDrop1"](target,dragEvent);
			}
			else if (newType == DragEvent.DRAG_COMPLETE)
			{
			   	dragAutomationHandlerClass["recordAutomatableDragCancel1"]
			   		(NativeDragManager.dragInitiator as IUIComponent, dragEvent);
			}
		}    
            
        // Resend the event as a DragEvent.
        _dispatchDragEvent(target, dragEvent);
                
        if (newType == DragEvent.DRAG_COMPLETE)
        {
            if (sm == sandboxRoot)
                endDrag();
            else 
            {
                me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
                me.name = "endDrag";
                // trace("-->dispatch endDrag for DragManagerImpl", sm);
                sandboxRoot.dispatchEvent(me);
                // trace("<--dispatch endDrag for DragManagerImpl", sm);
            }
        }
    }

    /**
     *  @private
     */
    private function _dispatchDragEvent(target:DisplayObject, event:DragEvent):void
    {
        // in trusted mode, the target could be in another application domain
        // in untrusted mode, the mouse events shouldn't work so we shouldn't be here

        // same domain
        if (isSameOrChildApplicationDomain(target))
            target.dispatchEvent(event);
        else
        {
            // wake up all the other DragManagers
            var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.INIT_MANAGER_REQUEST);
            me.name = "mx.managers.IDragManagerImpl";
            sandboxRoot.dispatchEvent(me);
            // bounce this message off the sandbox root and hope
            // another DragManager picks it up
            var mde:InterDragManagerEvent = new InterDragManagerEvent(InterDragManagerEvent.DISPATCH_DRAG_EVENT, false, false,
                                                    event.localX,
                                                    event.localY,
                                                    event.relatedObject,
                                                    event.ctrlKey,
                                                    event.altKey,
                                                    event.shiftKey,
                                                    event.buttonDown,
                                                    event.delta,
                                                    target,
                                                    event.type,
                                                    event.dragInitiator,
                                                    event.dragSource,
                                                    event.action,
                                                    event.draggedItem
                                                    );
            sandboxRoot.dispatchEvent(mde);
        }
    }

    private function isSameOrChildApplicationDomain(target:Object):Boolean
    {
        var swfRoot:DisplayObject = SystemManager.getSWFRoot(target);
        if (swfRoot)
            return true;


			dataFetcher.format = format;
						
			_clipboard.setDataHandler(format, dataFetcher.getDragSourceData, false);
		}	
		
		if (!dragImage)
		{
			// No drag image specified, use default
			var dragManagerStyleDeclaration:CSSStyleDeclaration =
				StyleManager.getStyleDeclaration("DragManager");
			var dragImageClass:Class =
				dragManagerStyleDeclaration.getStyle("defaultDragImageSkin");
			dragImage = new dragImageClass();
			proxyWidth = dragInitiator ? dragInitiator.width : 0;
			proxyHeight = dragInitiator ? dragInitiator.height : 0;
			if (dragImage is IFlexDisplayObject)
				IFlexDisplayObject(dragImage).setActualSize(proxyWidth, proxyHeight);
		}
		else
		{
			proxyWidth = dragImage.width;
			proxyHeight = dragImage.height;
		}

		_dragImage = dragImage; 	
						
		if (dragImage is IUIComponent && dragImage is ILayoutManagerClient && 
			!ILayoutManagerClient(dragImage).initialized && dragInitiator)
		{
			dragImage.addEventListener(FlexEvent.UPDATE_COMPLETE,initiateDrag);
			dragInitiator.systemManager.popUpChildren.addChild(DisplayObject(dragImage));
						
			if (dragImage is ILayoutManagerClient )
			{
				UIComponentGlobals.layoutManager.validateClient(ILayoutManagerClient(dragImage), true);
			}
			
			if(dragImage is IUIComponent)
			{
				dragImage.setActualSize(proxyWidth, proxyHeight);
				proxyWidth = (dragImage as IUIComponent).getExplicitOrMeasuredWidth();
				proxyHeight = (dragImage as IUIComponent).getExplicitOrMeasuredHeight();
			}
			else
			{
				proxyWidth = dragImage.measuredWidth;
				proxyHeight = dragImage.measuredHeight;
			}
			
			if (dragImage is ILayoutManagerClient )
			{
				UIComponentGlobals.layoutManager.validateClient(ILayoutManagerClient(dragImage));
			}
		}
		else
		{ 
			initiateDrag(null, false);
			return;
		}
	}
	
	/**
	 *  Finish up the doDrag once the dragImage has been drawn
	 */ 
	private function initiateDrag(event:FlexEvent, removeImage:Boolean = true):void
	{
		if (removeImage)
			_dragImage.removeEventListener(FlexEvent.UPDATE_COMPLETE, initiateDrag);
		var dragBitmap:BitmapData 	
		if (_dragImage.width && _dragImage.height)
			dragBitmap = new BitmapData(_dragImage.width, _dragImage.height, true, 0x000000);
		else
			dragBitmap = new BitmapData(1, 1, true, 0x000000);
		dragBitmap.draw(_dragImage);
		
		if (removeImage && _dragImage is IUIComponent && _dragInitiator)		
		{
			_dragInitiator.systemManager.popUpChildren.removeChild(DisplayObject(_dragImage));
		}
		
		// TODO!!! include _dragActions as the last param
		flash.desktop.NativeDragManager.doDrag(InteractiveObject(_dragInitiator), _clipboard, dragBitmap, _offset, _allowedActions); 
		//NativeDragManager.dropAction = _allowMove ? DragManager.MOVE : DragManager.COPY;
	}
	
	/**
	 *  Call this method from your <code>dragEnter</code> event handler if you accept
	 *  the drag/drop data.
	 *  For example: 
	 *
	 *  <pre>DragManager.acceptDragDrop(event.target);</pre>
	 *
	 *	@param target The drop target accepting the drag.
	 */
	public function acceptDragDrop(target:IUIComponent):void
	{
		if (isDragging)
		{
			// trace("NativeDragMgr.acceptDragDrop targ",target);
			var dispObj:InteractiveObject = target as InteractiveObject;
			if (dispObj)
				flash.desktop.NativeDragManager.acceptDragDrop(dispObj);
		}
		else
		{
			var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
			me.name = "acceptDragDrop";
			me.value = target;
			// trace("-->dispatch acceptDragDrop for DragManagerImpl", sm, target);
			sandboxRoot.dispatchEvent(me);
			// trace("<--dispatch acceptDragDrop for DragManagerImpl", sm, target);
		}
	}
	
	/**
	 *  Sets the feedback indicator for the drag and drop operation.
	 *  Possible values are <code>DragManager.COPY</code>, <code>DragManager.MOVE</code>,
	 *  <code>DragManager.LINK</code>, or <code>DragManager.NONE</code>.
	 *
	 *  @param feedback The type of feedback indicator to display.
	 */
	public function showFeedback(feedback:String):void
	{
		if (isDragging)
		{
			if (feedback == DragManager.MOVE && !_allowedActions.allowMove)
				return;
			else if (feedback == DragManager.COPY && !_allowedActions.allowCopy)
				return;
			else if (feedback == DragManager.LINK && !_allowedActions.allowLink)
				return;
			flash.desktop.NativeDragManager.dropAction = feedback;
		}
		else
		{
			var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
			me.name = "showFeedback";
			me.value = feedback;
			// trace("-->dispatch showFeedback for DragManagerImpl", sm, feedback);
			sandboxRoot.dispatchEvent(me);
			// trace("<--dispatch showFeedback for DragManagerImpl", sm, feedback);
		}
	}
	
	/**
	 *  Returns the current drag and drop feedback.
	 *
	 *  @return  Possible return values are <code>DragManager.COPY</code>, 
	 *  <code>DragManager.MOVE</code>,
	 *  <code>DragManager.LINK</code>, or <code>DragManager.NONE</code>.
	 */
	public function getFeedback():String
	{
		if (!isDragging)
		{
			var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
			me.name = "getFeedback";
			// trace("-->dispatch getFeedback for DragManagerImpl", sm);
			sandboxRoot.dispatchEvent(me);
			// trace("<--dispatch getFeedback for DragManagerImpl", sm);
			return me.value as String;
		}

		return flash.desktop.NativeDragManager.dropAction;
	}
	
	/**
	 *  @Review
	 *  Not Supported by NativeDragManagerImpl
	 */
	public function endDrag():void
	{
		var me:InterManagerRequest;

		me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "mouseShield";
		me.value = false;
		// trace("-->dispatch remove mouseShield.for DragManagerImpl", sm);
		sandboxRoot.dispatchEvent(me);
		
		me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "isDragging";
		me.value = false;
		// trace("-->dispatch isDragging for DragManagerImpl", sm, false);
		sandboxRoot.dispatchEvent(me);
		// trace("<--dispatch isDragging for DragManagerImpl", sm, false);
		// trace("<--endDrag for DragManagerImpl", sm);

	}
			
	/**
	 *  @private
	 *  register ISystemManagers that will listen for events 
	 *  (such as those for additional windows)
	 */
	mx_internal function registerSystemManager(sm:ISystemManager):void
	{
		if (sm.isTopLevel())
		{
			sm.addEventListener(MouseEvent.MOUSE_DOWN, sm_mouseDownHandler);
			sm.addEventListener(MouseEvent.MOUSE_UP, sm_mouseUpHandler);
		}

		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, nativeDragEventHandler, true);
		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_COMPLETE, nativeDragEventHandler, true);
		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, nativeDragEventHandler, true);
		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_EXIT, nativeDragEventHandler, true);
		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_OVER, nativeDragEventHandler, true);
		sm.stage.addEventListener(NativeDragEvent.NATIVE_DRAG_START, nativeDragEventHandler, true); 

	}
	
	/**
	 *  @private
	 *  unregister ISystemManagers that will listen for events 
	 *  (such as those for additional windows)
	 */
	mx_internal function unregisterSystemManager(sm:ISystemManager):void
	{
		if (sm.isTopLevel())
		{
			sm.removeEventListener(MouseEvent.MOUSE_DOWN, sm_mouseDownHandler);
			sm.removeEventListener(MouseEvent.MOUSE_UP, sm_mouseUpHandler);
		}

		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, nativeDragEventHandler, true);
		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_COMPLETE, nativeDragEventHandler, true);
		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_DROP, nativeDragEventHandler, true);
		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_EXIT, nativeDragEventHandler, true);
		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_OVER, nativeDragEventHandler, true);
		sm.stage.removeEventListener(NativeDragEvent.NATIVE_DRAG_START, nativeDragEventHandler, true); 

	}
	
	//--------------------------------------------------------------------------
	//
	//  Event handlers
	//
	//--------------------------------------------------------------------------
	private function sm_mouseDownHandler(event:MouseEvent):void
	{
		mouseIsDown = true;
	}

	private function sm_mouseUpHandler(event:MouseEvent):void
	{
		mouseIsDown = false;
	}
	
	/**
	 *  Listens for all NativeDragEvents and then redispatches them as DragEvents 
	 */
	private function nativeDragEventHandler(event:NativeDragEvent):void
	{
		var newType:String = event.type.charAt(6).toLowerCase() + event.type.substr(7);
		var dragSource:DragSource = new DragSource();
		var target:DisplayObject = event.target as DisplayObject;		
		var clipboard:Clipboard = event.clipboard;
		var origFormats:Array = clipboard.formats;
		var len:int = origFormats.length;
		var format:String;
		var data:Object;
		var me:InterManagerRequest;
		
		_allowedActions = event.allowedActions;
		
		//translate either commandKey or controlKey to old-style ctrlKey 
		var ctrlKey:Boolean = false;
		if (Capabilities.os.substring(0,3) == "Mac")
			ctrlKey = event.commandKey;
		else
			ctrlKey = event.controlKey;	
		//default to move if drag is from same app
	
                if (NativeDragManager.dragInitiator && event.type == NativeDragEvent.NATIVE_DRAG_START)
                {
                    flash.desktop.NativeDragManager.dropAction =  
                        (ctrlKey || !_allowMove) ? DragManager.COPY : DragManager.MOVE;
                }
	
		// Transfer clipboard data to dragSource	
		if (event.type != NativeDragEvent.NATIVE_DRAG_EXIT)
		{
			for (var i:int = 0; i < len; i++)
			{ 
				format = origFormats[i];
				if (clipboard.hasFormat(format))
				{
					// Create an object to store a reference to the format and clipboard.
					// This delays copying over the drag data until it is needed					
					var dataFetcher:DragDataFormatFetcher = new DragDataFormatFetcher();
