using C4IT.FASD.Base;

using F4SD_AdaptableIcon.Enums;

using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.CustomEvents;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Pages.CustomMessageBox
{
    public partial class CustomMessageBox : CustomPopupBase, IBlurInvoker, INotifyPropertyChanged
    {
        #region Properties

        private bool isCanceled = false;

        #region Caption

        private string _Caption = null;
        public string Caption
        {
            get { return _Caption; }
            set { if (value != _Caption) { _Caption = value; OnPropertyChanged("Caption"); } }
        }

        #endregion

        #region Message

        private string _Message = null;
        public string Message
        {
            get { return _Message; }
            set { if (value != _Message) { _Message = value; OnPropertyChanged("Message"); } }
        }

        #endregion

        #region CenterText

        private bool _CenterText = false;
        public bool CenterText
        {
            get { return _CenterText; }
            set { if (value != _CenterText) { _CenterText = value; OnPropertyChanged("CenterText"); } }
        }

        #endregion

        #region HasYesNoButtons


        private bool _HasYesNoButtons = false;

        public bool HasYesNoButtons
        {
            get { return _HasYesNoButtons; }
            set { if (value != _HasYesNoButtons) { _HasYesNoButtons = value; OnPropertyChanged("HasYesNoButtons"); } }
        }

        #endregion


        #region HasYesNoText


        private bool _HasYesNoText = false;
        public bool HasYesNoText
        {
            get { return _HasYesNoText; }
            set { if (value != _HasYesNoText) { _HasYesNoText = value; OnPropertyChanged("HasYesNoText"); } }
        }

        #endregion

        public event PropertyChangedEventHandler PropertyChanged;

        public int ResultIndex { get; private set; } = -1;

        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        #endregion

        private CustomMessageBox()
        {
            InitializeComponent();
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            cFocusInvoker.GotFocus += ElementGotFocus;
            cFocusInvoker.LostFocus += ElementLostFocus;
        }

        private void SetLevel(enumHealthCardStateLevel level)
        {
            StatusIcon.Visibility = Visibility.Visible;

            switch (level)
            {
                case enumHealthCardStateLevel.None:
                    StatusIcon.Visibility = Visibility.Collapsed;
                    StatusIcon.SelectedInternIcon = enumInternIcons.none;
                    break;
                case enumHealthCardStateLevel.Ok:
                    StatusIcon.SelectedInternIcon = enumInternIcons.status_good;
                    StatusIcon.PrimaryIconColor = (SolidColorBrush)Application.Current.FindResource("Color.Green");
                    break;
                case enumHealthCardStateLevel.Warning:
                    StatusIcon.SelectedInternIcon = enumInternIcons.status_danger;
                    StatusIcon.PrimaryIconColor = (SolidColorBrush)Application.Current.FindResource("Color.Orange");
                    break;
                case enumHealthCardStateLevel.Error:
                    StatusIcon.SelectedInternIcon = enumInternIcons.status_bad;
                    StatusIcon.PrimaryIconColor = (SolidColorBrush)Application.Current.FindResource("Color.Red");
                    break;
                case enumHealthCardStateLevel.Info:
                    StatusIcon.SelectedInternIcon = enumInternIcons.status_info;
                    StatusIcon.PrimaryIconColor = (SolidColorBrush)Application.Current.FindResource("Color.Blue");
                    break;
                default:
                    StatusIcon.SelectedInternIcon = enumInternIcons.f4sd;
                    break;
            }
        }

        private static CustomMessageBox InitializeMessageBox(string Message, string Caption, enumHealthCardStateLevel Level, Window Owner, bool HasYesNoButtons, bool HasYesNoText, List<string> MultiButtonText, bool TopMost, bool CenterScreen)
        {
            try
            {
                if (Owner != null)
                    cUtility.BringWindowToFront(Owner);

                var existingMessageBox = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is CustomMessageBox);
                if (existingMessageBox != null)
                {
                    existingMessageBox.Show();
                    return null;
                }


                CustomMessageBox messageBox = new CustomMessageBox();

                if (MultiButtonText != null)
                {
                    HasYesNoButtons = false;
                    HasYesNoText = false;
                    messageBox.MultiButtons.Visibility = Visibility.Visible;
                    messageBox.MultiButtons.SetButtonText(MultiButtonText);
                }

                messageBox.Message = Message;
                messageBox.Caption = Caption;
                messageBox.SetLevel(Level);
                messageBox.HasYesNoButtons = HasYesNoButtons;
                messageBox.HasYesNoText = HasYesNoText;
                messageBox.Topmost = TopMost;

                try
                {
                    messageBox.Owner = Owner;
                }
                catch { }
                if (!CenterScreen && Owner != null && Owner.Visibility == Visibility.Visible)
                    messageBox.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                else
                    messageBox.WindowStartupLocation = WindowStartupLocation.CenterScreen;

                return messageBox;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return null;
        }

        public static int Show(string Message, List<string> MultiButtonText, string Caption = null, enumHealthCardStateLevel Level = enumHealthCardStateLevel.None, Window Owner = null, bool TopMost = false, bool CenterScreen = false, int MaxWidth = -1)
        {
            var messageBox = InitializeMessageBox(Message, Caption, Level, Owner, false, false, MultiButtonText, TopMost, CenterScreen);
            if (messageBox == null)
                return -1;
            if (MaxWidth > 0)
                messageBox.MaxWidth = MaxWidth;
            messageBox.ShowDialog();
            return messageBox.ResultIndex;
        }

        public static bool? Show(string Message, string Caption = null, enumHealthCardStateLevel Level = enumHealthCardStateLevel.None, Window Owner = null, bool HasYesNoButtons = false, bool HasYesNoText = false, bool TopMost = false, bool CenterScreen = false)
        {
            var messageBox = InitializeMessageBox(Message, Caption, Level, Owner, HasYesNoButtons, HasYesNoText, null, TopMost, CenterScreen);
            if (messageBox == null)
                return null;

            var dialogResult = messageBox.ShowDialog();
            return messageBox.isCanceled ? null : dialogResult;
        }

        #region Close_Click

        private void Close_Click()
        {
            DialogResult = null;
            isCanceled = true;
            Close();
        }

        private void Close_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Close_Click();
        }

        private void Close_TouchDown(object sender, TouchEventArgs e)
        {
            Close_Click();
        }

        #endregion

        #region Internal Focus Events

        private void ElementGotFocus(object sender, EventArgs e)
        {
            try
            {
                FocusBorder.Visibility = Visibility.Visible;

                if (!(sender is FrameworkElement senderElement))
                    return;

                if (FocusBorder.IsVisible is false)
                    return;

                var desiredHeight = senderElement.ActualHeight;
                var desiredWidth = senderElement.ActualWidth;

                FrameworkElement placeHolderElement = new FrameworkElement() { Height = desiredHeight, Width = desiredWidth, Margin = senderElement.Margin };
                FocusDecorator.Height = desiredHeight + senderElement.Margin.Top + senderElement.Margin.Bottom;
                FocusDecorator.Width = desiredWidth + senderElement.Margin.Left + senderElement.Margin.Right;

                Point relativePoint = senderElement.TransformToAncestor(this)
                  .Transform(new Point(0, 0));

                if (senderElement.Parent is Decorator actualParentDecorator)
                    actualParentDecorator.Child = placeHolderElement;
                else if (senderElement.Parent is Panel actualParentPanel)
                {
                    if (actualParentPanel is Grid)
                    {
                        Grid.SetColumn(placeHolderElement, Grid.GetColumn(senderElement));
                        Grid.SetRow(placeHolderElement, Grid.GetRow(senderElement));
                    }

                    actualParentPanel.Children.Insert(actualParentPanel.Children.IndexOf(senderElement), placeHolderElement);
                    actualParentPanel.Children.Remove(senderElement);
                }

                Canvas.SetLeft(FocusDecorator, relativePoint.X - (senderElement.Margin.Left));
                Canvas.SetTop(FocusDecorator, relativePoint.Y - senderElement.Margin.Top);

                FocusDecorator.Child = senderElement;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void ElementLostFocus(object sender, EventArgs e)
        {
            try
            {
                FocusBorder.Visibility = Visibility.Collapsed;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        private void CustomMessageBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Escape:
                    Close_Click();
                    break;
            }
        }

        private void DoCloseAction(bool IsClose)
        {
            DialogResult = IsClose;
            Close();
            return;
        }

        private void YesNoButton_ButtonHasBeenClicked(object sender, BooleanEventArgs e)
        {
            try
            {
                DoCloseAction(e.BooleanArg);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void MultiButtons_ResultChanged(object sender, MultiButtonEventArgs e)
        {
            ResultIndex = e.ResultIndex;
            Close();
        }

        public override void Dispose()
        {
            base.Dispose();
            Close();
        }
    }
}
