using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;

namespace RowDragDrop
{
    internal class DragAdorner : Adorner
    {
        private readonly UIElement child;
        private double leftOffset;
        private double topOffset;

        public DragAdorner(UIElement owner)
            : base(owner)
        {
        }

        public DragAdorner(UIElement owner, UIElement adornElement, bool useVisualBrush, double opacity)
            : base(owner)
        {
            if (useVisualBrush)
            {
                var brush = new VisualBrush(adornElement);
                brush.Opacity = opacity;
                var rectangle = new Rectangle();

                if (adornElement != null)
                {
                    var adornFrameworkElement = ((FrameworkElement)adornElement);

                    rectangle.Width = adornFrameworkElement.DesiredSize.Width;
                    rectangle.Height = adornFrameworkElement.DesiredSize.Height;

//                    rectangle.Width = adornFrameworkElement.ActualWidth;
//                    rectangle.Height = adornFrameworkElement.ActualHeight;

                    rectangle.Fill = brush;
                    this.child = rectangle;
                }
            }
            else
            {
                this.child = adornElement;
            }
        }

        public double LeftOffset
        {
            get
            {
                return this.leftOffset;
            }
            set
            {
                this.leftOffset = value;
                this.UpdatePosition();
            }
        }

        public double TopOffset
        {
            get
            {
                return this.topOffset;
            }
            set
            {
                this.topOffset = value;
                this.UpdatePosition();
            }
        }

        protected override int VisualChildrenCount
        {
            get
            {
                return 1;
            }
        }

        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            var result = new GeneralTransformGroup();

            result.Children.Add(base.GetDesiredTransform(transform));
            result.Children.Add(new TranslateTransform(this.leftOffset, this.topOffset));

            return result;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            this.child.Arrange(new Rect(this.child.DesiredSize));

            return finalSize;
        }

        protected override Visual GetVisualChild(int index)
        {
            return this.child;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            this.child.Measure(availableSize);

            return this.child.DesiredSize;
        }

        private void UpdatePosition()
        {
            var adorner = (AdornerLayer)this.Parent;
            if (adorner != null)
            {
                adorner.Update(this.AdornedElement);
            }
        }
    }
}