/// <summary>
    /// Initializes a new instance of the DropInfo class.
    /// </summary>
    /// 
    /// <param name="sender">
    /// The sender of the drag event.
    /// </param>
    /// 
    /// <param name="e">
    /// The drag event.
    /// </param>
    /// 
    /// <param name="dragInfo">
    /// Information about the source of the drag, if the drag came from within the framework.
    /// </param>
    public DropInfo(object sender, DragEventArgs e, DragInfo dragInfo)
    {
      var dataFormat = DragDrop.DataFormat.Name;
      this.Data = (e.Data.GetDataPresent(dataFormat)) ? e.Data.GetData(dataFormat) : e.Data;
      this.DragInfo = dragInfo;
      this.KeyStates = e.KeyStates;

      this.VisualTarget = sender as UIElement;
      // if there is no drop target, find another
      if (!this.VisualTarget.IsDropTarget())
      {
        // try to find next element
        var element = this.VisualTarget.TryGetNextAncestorDropTargetElement();
        if (element != null)
        {
          this.VisualTarget = element;
        }
      }
      // visual target can be null, so give us a point...
      this.DropPosition = this.VisualTarget != null ? e.GetPosition(this.VisualTarget) : new Point();

      if (this.VisualTarget is TabControl) {
        if (!HitTestUtilities.HitTest4Type<TabPanel>(this.VisualTarget, this.DropPosition)) {
          return;
        }
      }

      if (this.VisualTarget is ItemsControl) {
        var itemsControl = (ItemsControl)this.VisualTarget;
        //System.Diagnostics.Debug.WriteLine(">>> Name = {0}", itemsControl.Name);
        // get item under the mouse
        item = itemsControl.GetItemContainerAt(this.DropPosition);
        var directlyOverItem = item != null;

        this.TargetGroup = itemsControl.FindGroup(this.DropPosition);
        this.VisualTargetOrientation = itemsControl.GetItemsPanelOrientation();
        this.VisualTargetFlowDirection = itemsControl.GetItemsPanelFlowDirection();

        if (item == null) {
          // ok, no item found, so maybe we can found an item at top, left, right or bottom
          item = itemsControl.GetItemContainerAt(this.DropPosition, this.VisualTargetOrientation);
          directlyOverItem = false;
        }

        if (item == null && this.TargetGroup != null && this.TargetGroup.IsBottomLevel)
        {
          var itemData = this.TargetGroup.Items.FirstOrDefault();
          if (itemData != null)
          {
            item = itemsControl.ItemContainerGenerator.ContainerFromItem(itemData) as UIElement;
            directlyOverItem = false;
          }
        }

        if (item != null)
        {
          itemParent = ItemsControl.ItemsControlFromItemContainer(item);
          this.VisualTargetOrientation = itemParent.GetItemsPanelOrientation();
          this.VisualTargetFlowDirection = itemParent.GetItemsPanelFlowDirection();

          this.InsertIndex = itemParent.ItemContainerGenerator.IndexFromContainer(item);
          this.TargetCollection = itemParent.ItemsSource ?? itemParent.Items;

          var tvItem = item as TreeViewItem;
          
          if (directlyOverItem || tvItem != null)
          {
            this.TargetItem = itemParent.ItemContainerGenerator.ItemFromContainer(item);
            this.VisualTargetItem = item;
          }

          var itemRenderSize = item.RenderSize;

          if (this.VisualTargetOrientation == Orientation.Vertical) {
            var currentYPos = e.GetPosition(item).Y;
            var targetHeight = itemRenderSize.Height;

            if (currentYPos > targetHeight / 2) {
              this.InsertIndex++;
              this.InsertPosition = RelativeInsertPosition.AfterTargetItem;
            } else {
              this.InsertPosition = RelativeInsertPosition.BeforeTargetItem;
            }

            if (currentYPos > targetHeight * 0.25 && currentYPos < targetHeight * 0.75) {
              if (tvItem != null)
              {
                this.TargetCollection = tvItem.ItemsSource ?? tvItem.Items;
                this.InsertIndex = this.TargetCollection != null ? this.TargetCollection.OfType<object>().Count() : 0;
              }
              this.InsertPosition |= RelativeInsertPosition.TargetItemCenter;
            }
            //System.Diagnostics.Debug.WriteLine("==> DropInfo: pos={0}, idx={1}, Y={2}, Item={3}", this.InsertPosition, this.InsertIndex, currentYPos, item);
          }
          else {
            var currentXPos = e.GetPosition(item).X;
            var targetWidth = itemRenderSize.Width;

            if (this.VisualTargetFlowDirection == FlowDirection.RightToLeft) {
              if (currentXPos > targetWidth / 2) {
                this.InsertPosition = RelativeInsertPosition.BeforeTargetItem;
              } else {
                this.InsertIndex++;
                this.InsertPosition = RelativeInsertPosition.AfterTargetItem;
              }
            } else if (this.VisualTargetFlowDirection == FlowDirection.LeftToRight) {
              if (currentXPos > targetWidth / 2) {
                this.InsertIndex++;
                this.InsertPosition = RelativeInsertPosition.AfterTargetItem;
              } else {
                this.InsertPosition = RelativeInsertPosition.BeforeTargetItem;
              }
            }

            if (currentXPos > targetWidth * 0.25 && currentXPos < targetWidth * 0.75) {
              if (tvItem != null)
              {
                this.TargetCollection = tvItem.ItemsSource ?? tvItem.Items;
                this.InsertIndex = this.TargetCollection != null ? this.TargetCollection.OfType<object>().Count() : 0;
              }
              this.InsertPosition |= RelativeInsertPosition.TargetItemCenter;
            }
            //System.Diagnostics.Debug.WriteLine("==> DropInfo: pos={0}, idx={1}, X={2}, Item={3}", this.InsertPosition, this.InsertIndex, currentXPos, item);
          } 
        }
        else
        {
          this.TargetCollection = itemsControl.ItemsSource ?? itemsControl.Items;
          this.InsertIndex = itemsControl.Items.Count;
          //System.Diagnostics.Debug.WriteLine("==> DropInfo: pos={0}, item=NULL, idx={1}", this.InsertPosition, this.InsertIndex);
        }
      } else {
          this.VisualTargetItem = this.VisualTarget; 
      }
    }