using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;

namespace HandyControl.Controls
{
    /// <summary>
    ///     弹出窗口
    /// </summary>
    [TemplatePart(Name = ElementMainBorder, Type = typeof(Border))]
    [TemplatePart(Name = ElementTitleBlock, Type = typeof(TextBlock))]
    public class PopupWindow : System.Windows.Window
    {
        #region Constants

        private const string ElementMainBorder = "PART_MainBorder";

        private const string ElementTitleBlock = "PART_TitleBlock";

        #endregion Constants

        private Border _mainBorder;

        private TextBlock _titleBlock;

        private bool _showBackground = true;

        private FrameworkElement _targetElement;

        public override void OnApplyTemplate()
        {
            if (_titleBlock != null)
            {
                _titleBlock.MouseLeftButtonDown -= TitleBlock_OnMouseLeftButtonDown;
            }

            base.OnApplyTemplate();

            _mainBorder = GetTemplateChild(ElementMainBorder) as Border;
            _titleBlock = GetTemplateChild(ElementTitleBlock) as TextBlock;

            if (_titleBlock != null)
            {
                _titleBlock.MouseLeftButtonDown += TitleBlock_OnMouseLeftButtonDown;
            }

            if (PopupElement != null)
            {
                _mainBorder.Child = PopupElement;
            }
        }

        internal static readonly DependencyProperty ContentStrProperty = DependencyProperty.Register(
            "ContentStr", typeof(string), typeof(PopupWindow), new PropertyMetadata(default(string)));

        internal string ContentStr
        {
            get => (string) GetValue(ContentStrProperty);
            set => SetValue(ContentStrProperty, value);
        }

        private bool IsDialog { get; set; }

        public PopupWindow()
        {
            CommandBindings.Add(new CommandBinding(ControlCommands.Close, CloseButton_OnClick));
            CommandBindings.Add(new CommandBinding(ControlCommands.Confirm, ButtonOk_OnClick));
            CommandBindings.Add(new CommandBinding(ControlCommands.Cancel, ButtonCancle_OnClick));

            Closing += (sender, args) =>
            {
                if (!IsDialog)
                    Owner?.Focus();
            };
            Loaded += (s, e) =>
            {
                if (!_showBackground)
                {
                    var point = ArithmeticHelper.CalSafePoint(_targetElement, PopupElement, BorderThickness);
                    Left = point.X;
                    Top = point.Y;
                    Opacity = 1;
                }
            };
            try
            {
                Owner = Application.Current.MainWindow;
            }
            catch
            {
                // ignored
            }
        }

        public PopupWindow(System.Windows.Window owner) : this() => Owner = owner;

        private void CloseButton_OnClick(object sender, RoutedEventArgs e) => Close();

        public FrameworkElement PopupElement { get; set; }

        public static readonly DependencyProperty ShowTitleProperty = DependencyProperty.Register(
            "ShowTitle", typeof(bool), typeof(PopupWindow), new PropertyMetadata(ValueBoxes.TrueBox));

        public bool ShowTitle
        {
            get => (bool) GetValue(ShowTitleProperty);
            set => SetValue(ShowTitleProperty, ValueBoxes.BooleanBox(value));
        }

        public static readonly DependencyProperty ShowCancelProperty = DependencyProperty.Register(
            "ShowCancel", typeof(bool), typeof(PopupWindow), new PropertyMetadata(ValueBoxes.FalseBox));

        public bool ShowCancel
        {
            get => (bool) GetValue(ShowCancelProperty);
            set => SetValue(ShowCancelProperty, ValueBoxes.BooleanBox(value));
        }

        public static readonly DependencyProperty ShowBorderProperty = DependencyProperty.Register(
            "ShowBorder", typeof(bool), typeof(PopupWindow), new PropertyMetadata(ValueBoxes.FalseBox));

        public bool ShowBorder
        {
            get => (bool) GetValue(ShowBorderProperty);
            set => SetValue(ShowBorderProperty, ValueBoxes.BooleanBox(value));
        }

        private void TitleBlock_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                DragMove();
            }
        }

        public void Show(FrameworkElement element, bool showBackground = true)
        {
            if (!showBackground)
            {
                Opacity = 0;
                AllowsTransparency = true;
                WindowStyle = WindowStyle.None;
                ShowTitle = false;
                MinWidth = 0;
                MinHeight = 0;
            }

            _showBackground = showBackground;
            _targetElement = element;
            Show();
        }

        public void ShowDialog(FrameworkElement element, bool showBackground = true)
        {
            if (!showBackground)
            {
                Opacity = 0;
                AllowsTransparency = true;
                WindowStyle = WindowStyle.None;
                ShowTitle = false;
                MinWidth = 0;
                MinHeight = 0;
            }

            _showBackground = showBackground;
            _targetElement = element;
            ShowDialog();
        }

        public void Show(System.Windows.Window element, Point point)
        {
            Left = element.Left + point.X;
            Top = element.Top + point.Y;
            Show();
        }

        public static void Show(string message)
        {
            var window = new PopupWindow
            {
                AllowsTransparency = true,
                WindowStyle = WindowStyle.None,
                ContentStr = message,
                WindowStartupLocation = WindowStartupLocation.CenterScreen,
                Background = ResourceHelper.GetResource<Brush>(ResourceToken.PrimaryBrush)
            };
            window.Show();
        }

        public static bool? ShowDialog(string message, string title = default, bool showCancel = false)
        {
            var window = new PopupWindow
            {
                AllowsTransparency = true,
                WindowStyle = WindowStyle.None,
                ContentStr = message,
                IsDialog = true,
                WindowStartupLocation = WindowStartupLocation.CenterScreen,
                ShowBorder = true,
                Title = string.IsNullOrEmpty(title) ? Properties.Langs.Lang.Tip : title,
                ShowCancel = showCancel
            };
            return window.ShowDialog();
        }

        private void ButtonOk_OnClick(object sender, RoutedEventArgs e)
        {
            if (IsDialog)
            {
                DialogResult = true;
            }
            Close();
        }

        private void ButtonCancle_OnClick(object sender, RoutedEventArgs e)
        {
            if (IsDialog)
            {
                DialogResult = false;
            }
            Close();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            PopupElement = null;
        }
    }
}
