// DragDropLibrary.cs
// Copyright (c) 2016 Bentley Systems, Incorporated. All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using System.Text;


namespace Haestad.Framework.UI.Integration
{
    /// <summary>
    /// Class provides utility methods for mapping System.Windows.Forms to System.Windows and vice versa for DragDrop constructs.
    /// </summary>
    internal sealed class DragDropLibrary
    {
        #region Internal Static Methods
        // Note: <whar> Covered by reflective unit test. If signature changes, test will fail.
        internal static System.Windows.Forms.DragEventArgs ConvertDragEventArgs(System.Windows.DragEventArgs e, System.Windows.IInputElement relativeToElement)
        {
            System.Windows.Point location = e.GetPosition(relativeToElement);
            System.Windows.Forms.DragDropEffects allowedEffects = ConvertSystemWindowsDragDropEffects(e.AllowedEffects);
            System.Windows.Forms.DragDropEffects effect = ConvertSystemWindowsDragDropEffects(e.Effects);
            DragDropDataObjectWrapper dragDropDataObject = new DragDropDataObjectWrapper(e.Data);

            return new DragEventArgs(dragDropDataObject,
                (int)e.KeyStates, (int)location.X, (int)location.Y, allowedEffects, effect);
        }

        // Note: <whar> Covered by reflective unit test. If signature changes, test will fail.
        internal static System.Windows.DragDropEffects ConvertSystemWindowsFormsDragDropEffects(DragDropEffects dragDropEffects)
        {
            if (dragDropEffects == DragDropEffects.None)
                return System.Windows.DragDropEffects.None;

            if (dragDropEffects == DragDropEffects.All)
                return System.Windows.DragDropEffects.All;

            if (dragDropEffects == DragDropEffects.Scroll)
                return System.Windows.DragDropEffects.Scroll;

            System.Windows.DragDropEffects swDropEffects = System.Windows.DragDropEffects.None;

            if ((dragDropEffects & DragDropEffects.Copy) > 0)
                swDropEffects |= System.Windows.DragDropEffects.Copy;

            if ((dragDropEffects & DragDropEffects.Move) > 0)
                swDropEffects |= System.Windows.DragDropEffects.Move;

            if ((dragDropEffects & DragDropEffects.Link) > 0)
                swDropEffects |= System.Windows.DragDropEffects.Link;

            return swDropEffects;
        }
        #endregion

        #region Private Static Methods
        // Note: <whar> Covered by reflective unit test. If signature changes, test will fail.
        private static DragDropEffects ConvertSystemWindowsDragDropEffects(System.Windows.DragDropEffects dragDropEffects)
        {
            if (dragDropEffects == System.Windows.DragDropEffects.None)
                return DragDropEffects.None;

            if (dragDropEffects == System.Windows.DragDropEffects.All)
                return DragDropEffects.All;

            if (dragDropEffects == System.Windows.DragDropEffects.Scroll)
                return DragDropEffects.Scroll;

            DragDropEffects swfDropEffects = DragDropEffects.None;

            if ((dragDropEffects & System.Windows.DragDropEffects.Copy) > 0)
                swfDropEffects |= DragDropEffects.Copy;

            if ((dragDropEffects & System.Windows.DragDropEffects.Move) > 0)
                swfDropEffects |= DragDropEffects.Move;

            if ((dragDropEffects & System.Windows.DragDropEffects.Link) > 0)
                swfDropEffects |= DragDropEffects.Link;

            return swfDropEffects;
        }
        #endregion

        #region Private Class (DragDropDataObjectWrapper)
        /// <summary>
        /// Class wraps a System.Windows.IDataObject instance and exposes it as a System.Windows.Forms.IDataObject instance.
        /// </summary>
        private class DragDropDataObjectWrapper : System.Windows.Forms.IDataObject
        {
            #region Constructor
            public DragDropDataObjectWrapper(System.Windows.IDataObject dataObject)
            {
                DataObject = dataObject;
            }
            #endregion

            #region IDataObject Members

            public object GetData(Type format)
            {
                return DataObject.GetData(format);
            }

            public object GetData(string format)
            {
                return DataObject.GetData(format);
            }

            public object GetData(string format, bool autoConvert)
            {
                return DataObject.GetData(format, autoConvert);
            }

            public bool GetDataPresent(Type format)
            {
                return DataObject.GetDataPresent(format);
            }

            public bool GetDataPresent(string format)
            {
                return DataObject.GetDataPresent(format);
            }

            public bool GetDataPresent(string format, bool autoConvert)
            {
                return DataObject.GetDataPresent(format, autoConvert);
            }

            public string[] GetFormats()
            {
                return DataObject.GetFormats();
            }

            public string[] GetFormats(bool autoConvert)
            {
                return DataObject.GetFormats(autoConvert);
            }

            public void SetData(object data)
            {
                DataObject.SetData(data);
            }

            public void SetData(Type format, object data)
            {
                DataObject.SetData(format, data);
            }

            public void SetData(string format, object data)
            {
                DataObject.SetData(format, data);
            }

            public void SetData(string format, bool autoConvert, object data)
            {
                DataObject.SetData(format, data, autoConvert);
            }

            #endregion

            #region Private Properties
            private System.Windows.IDataObject DataObject
            {
                get;
                set;
            }
            #endregion
        }
        #endregion
    }
}
