using DevExpress.Utils;
using DevExpress.Utils.Win;
using DevExpress.XtraBars.Docking2010;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.ButtonsPanelControl;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DxHelper
{
    /// <summary>
    /// Popup窗体弹出方向
    /// </summary>
    public enum EnumPopupDirection
    {
        /// <summary>
        /// 左侧弹出
        /// </summary>
        Left,

        /// <summary>
        /// 右侧弹出
        /// </summary>
        Right,

        /// <summary>
        /// 顶部弹出
        /// </summary>
        Top,

        /// <summary>
        /// 底部弹出
        /// </summary>
        Bottom,
    }

    /// <summary>
    /// Popup窗体弹出动画
    /// </summary>
    public enum EnumPopupAnimation
    {
        /// <summary>
        /// 无动画,立即显示或隐藏
        /// </summary>
        None,

        /// <summary>
        /// 颜色淡入淡出
        /// </summary>
        Fade,

        /// <summary>
        /// 抽屉滑入滑出
        /// </summary>
        Slide
    }
    public static class PopupHelper
    {
        private static Dictionary<Control, FlyoutPanel> dic = new Dictionary<Control, FlyoutPanel>();

        /// <summary>
        /// 从popup窗体中弹出content
        /// </summary>
        /// <param name="content">要显示的control,content必须是一个容器控件,如Panel、Form等</param>
        /// <param name="owner">popup窗体的父容器</param>
        /// <param name="size">popup窗体的大小,为0时将使用owner的大小</param>
        /// <param name="direct">窗体弹出位置</param>
        /// <param name="animation">弹出动画</param>
        /// <param name="showCloseButton">是否显示关闭按钮</param>
        /// <param name="autoClose">点击窗体外部是否自动关闭popup窗体</param>
        /// <param name="renderDone">渲染完成后的回调函数</param>
        public static void ShowPopup(Control content, Control owner, int size = 0, EnumPopupDirection direct = EnumPopupDirection.Right, EnumPopupAnimation animation = EnumPopupAnimation.Slide, bool showCloseButton = true, bool autoClose = false, Action renderDone = null)
        {
            foreach (var item in dic.Values)
            {
                item.HidePopup();
            }
            FlyoutPanel docker;
            if (!dic.ContainsKey(content))
            {
                docker = new FlyoutPanel();
                if (showCloseButton)
                {
                    docker.OptionsButtonPanel.ShowButtonPanel = true;
                    ButtonImageOptions options = new ButtonImageOptions();
                    options.SvgImage = SvgHelper.CreateClose();
                    options.SvgImageSize = new System.Drawing.Size(16, 16);
                    var btnClose = new PeekFormButton("", true, options, ButtonStyle.PushButton, "", -1, true, null, true, false, true, null, -1, false);
                    btnClose.Click += (sender, e) =>
                    {
                        docker.Tag = "btnClose";
                        docker?.HidePopup();
                    };
                    docker.OptionsButtonPanel.Buttons.Add(btnClose);
                    docker.OptionsButtonPanel.ButtonPanelContentAlignment = ContentAlignment.MiddleLeft;
                    docker.OptionsButtonPanel.ButtonPanelHeight = 24;
                }
                var panel = new FlyoutPanelControl(docker) { Dock = DockStyle.Fill };
                docker.Controls.Add(panel);
                dic.Add(content, docker);
            }
            else
                docker = dic[content];
            if (docker.IsPopupOpen)
                docker.HidePopup();
            else
            {
                if (owner != null)
                {
                    docker.OwnerControl = owner;
                }
                if (docker.OwnerControl == null)
                {
                    var parent = content.Parent;
                    while (!(parent is Form))
                    {
                        parent = parent.Parent;
                    }
                    docker.OwnerControl = parent;
                }
                if (size > 0)
                    docker.Width = docker.Height = size;
                else
                {
                    docker.Width = owner.Width;
                    docker.Height = owner.Height;
                    owner.SizeChanged += (sender, e) =>
                    {
                        if (docker.Parent != null)
                            docker.Parent.Size = new Size(owner.Width, owner.Height);
                    };
                }
                docker.Options.CloseOnOuterClick = autoClose;
                docker.Options.CloseOnHidingOwner = autoClose;
                if (animation == EnumPopupAnimation.Slide)
                    docker.Options.AnimationType = PopupToolWindowAnimation.Slide;
                else
                    docker.Options.AnimationType = PopupToolWindowAnimation.Fade;
                PopupToolWindowAnchor anchor = PopupToolWindowAnchor.Right;
                switch (direct)
                {
                    case EnumPopupDirection.Left:
                        anchor = PopupToolWindowAnchor.Left;
                        break;
                    case EnumPopupDirection.Right:
                        anchor = PopupToolWindowAnchor.Right;
                        break;
                    case EnumPopupDirection.Top:
                        anchor = PopupToolWindowAnchor.Top;
                        break;
                    case EnumPopupDirection.Bottom:
                        anchor = PopupToolWindowAnchor.Bottom;
                        break;
                }
                docker.Options.AnchorType = anchor;
                docker.Controls[0].Controls.Clear();
                content.Dock = DockStyle.Fill;
                if (content is Form)
                    content.Controls[0].Parent = docker.Controls[0];
                else
                    content.Parent = docker.Controls[0];
                bool immediate = animation == EnumPopupAnimation.None;
                docker.ShowPopup(immediate);
                docker.Shown += (sender, e) =>
                  {
                      renderDone?.Invoke();
                  };
            }
        }


        public static void HidePopup(Control content)
        {
            if (content.Parent == null || content.Parent.Parent == null) return;
            var docker = content.Parent.Parent as FlyoutPanel;
            docker?.HidePopup();
        }
    }
}
