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

import flash.events.NativeDragEvent;
import flash.geom.Point;
import flash.system.Capabilities;
import flash.utils.getDefinitionByName

import mx.core.DragSource;
import mx.core.IFlexDisplayObject;

public class NativeDragManagerImpl implements IDragManager
{
 
	//--------------------------------------------------------------------------
	//
	//  Class variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static var sm:ISystemManager;

	/**
	 *  @private
	 */
	private static var instance:IDragManager;

	//--------------------------------------------------------------------------
	//
	//  Class methods
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	public static function getInstance():IDragManager
	{
		if (!instance)
		{
			sm = SystemManagerGlobals.topLevelSystemManagers[0];
			instance = new NativeDragManagerImpl();
		}

		return instance;
	}

	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	public function NativeDragManagerImpl()
	{
		super();

		if (instance)
			throw new Error("Instance already exists.");
			
		registerSystemManager(sm);
		sandboxRoot = sm.getSandboxRoot();
		sandboxRoot.addEventListener(InterDragManagerEvent.DISPATCH_DRAG_EVENT, marshalDispatchEventHandler, false, 0, true);

		// trace("creating DragManagerImpl", sm);
		sandboxRoot.addEventListener(InterManagerRequest.DRAG_MANAGER_REQUEST, marshalDragManagerHandler, false, 0, true);
		var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "update";
		// trace("--->update request for DragManagerImpl", sm);
		sandboxRoot.dispatchEvent(me);
		// trace("<---update request for DragManagerImpl", sm);
	}

	//--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

	/**
	 *  @private
	 *  Object being dragged around.
	 */
	public var dragProxy:DragProxy;

	/**
	 *  @private
	 */
	private var mouseIsDown:Boolean = false;

	private var _action:String;

	/**
	 *  @private
	 */
	private var _dragInitiator:IUIComponent;
	
	/**
	 *  @private
	 */
	private var _clipboard:Clipboard;
	
	/**
	 *  @private
	 */
	private var _dragImage:IFlexDisplayObject;
	
	private var _offset:Point;
	
	private var _allowedActions:NativeDragOptions;
	
	private var _allowMove:Boolean;
	
	private var _relatedObject:InteractiveObject;
	
	/**
	 *  @private
	 *  The highest place we can listen for events in our DOM
	 */
	private var sandboxRoot:IEventDispatcher;

	//--------------------------------------------------------------------------
	//
	//  Properties
	//
	//--------------------------------------------------------------------------
		
	/**
	 *  Read-only property that returns <code>true</code>
	 *  if a drag is in progress.
	 */
	public function get isDragging():Boolean
	{
		return flash.desktop.NativeDragManager.isDragging;// || bDoingDrag;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	

	/**
	 *  Initiates a drag and drop operation.
	 *
	 *  @param dragInitiator IUIComponent that specifies the component initiating
	 *  the drag.
	 *
	 *  @param dragSource DragSource object that contains the data
	 *  being dragged.
	 *
	 *  @param mouseEvent The MouseEvent that contains the mouse information
	 *  for the start of the drag.
	 *
	 *  @param dragImage The image to drag. This argument is optional.
	 *  If omitted, a standard drag rectangle is used during the drag and
	 *  drop operation. If you specify an image, you must explicitly set a 
	 *  height and width of the image or else it will not appear.
	 *
	 *  @param xOffset Number that specifies the x offset, in pixels, for the
	 *  <code>dragImage</code>. This argument is optional. If omitted, the drag proxy
	 *  is shown at the upper-left corner of the drag initiator. The offset is expressed
	 *  in pixels from the left edge of the drag proxy to the left edge of the drag
	 *  initiator, and is usually a negative number.
	 *
	 *  @param yOffset Number that specifies the y offset, in pixels, for the
	 *  <code>dragImage</code>. This argument is optional. If omitted, the drag proxy
	 *  is shown at the upper-left corner of the drag initiator. The offset is expressed
	 *  in pixels from the top edge of the drag proxy to the top edge of the drag
	 *  initiator, and is usually a negative number.
	 *
	 *  @param imageAlpha Number that specifies the alpha value used for the
	 *  drag image. This argument is optional. If omitted, the default alpha
	 *  value is 0.5. A value of 0.0 indicates that the image is transparent;
	 *  a value of 1.0 indicates it is fully opaque. 
	 */
	public function doDrag(
			dragInitiator:IUIComponent, 
			dragSource:DragSource, 
			mouseEvent:MouseEvent,
			dragImage:IFlexDisplayObject = null, // instance of dragged item(s)
			xOffset:Number = 0,
			yOffset:Number = 0,
			imageAlpha:Number = 0.5,
			allowMove:Boolean = true):void
	{
		var proxyWidth:Number;
		var proxyHeight:Number;
		
		// Can't start a new drag if we're already in the middle of one...
		if (isDragging)
			return; 
		
		// Can't do a drag if the mouse isn't down
		if (!(mouseEvent.type == MouseEvent.MOUSE_DOWN ||
			  mouseEvent.type == MouseEvent.CLICK ||
			  mouseIsDown ||
			  mouseEvent.buttonDown)) 
		{ 
			return;
		}
		
		var me:InterManagerRequest = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "isDragging";
		me.value = true;
		// trace("-->dispatch isDragging for DragManagerImpl", sm, true);
		sandboxRoot.dispatchEvent(me);
		// trace("<--dispatch isDragging for DragManagerImpl", sm, true);
		
		me = new InterManagerRequest(InterManagerRequest.DRAG_MANAGER_REQUEST);
		me.name = "mouseShield";
		me.value = true;
		// trace("-->dispatch add mouseShield.for DragManagerImpl", sm);
		sandboxRoot.dispatchEvent(me);

		_clipboard = new Clipboard();
		_dragInitiator = dragInitiator;
		_offset = new Point(xOffset, yOffset);
		_allowMove = allowMove;
		
		//adjust offsets for imagePlacement.
		_offset.y -= InteractiveObject(dragInitiator).mouseY;
		_offset.x -= InteractiveObject(dragInitiator).mouseX;
		
		// TODO!!! We need to pass in these values as a function parameter
		_allowedActions = new NativeDragOptions();
		_allowedActions.allowCopy = true;
		_allowedActions.allowLink = true;
		_allowedActions.allowMove = allowMove;
		
		// Transfer the dragSource into a Clipboard
		for (var i:int = 0; i < dragSource.formats.length; i++)
		{
			var format:String = dragSource.formats[i] as String;
			
			// Create an object to store a reference to the format and dragSource.
			// This delays copying over the drag data until it is needed
