using FasdDesktopUi.Basics.Helper;
using FasdDesktopUi.Basics.Models;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Basics.UserControls
{
    public partial class CloseTicketDialog : UserControl
    {
        private static readonly Brush ValidationBrush = CreateValidationBrush();
        private static Brush CreateValidationBrush()
        {
            var brush = new SolidColorBrush(Color.FromRgb(0xF5, 0x7C, 0x73));
            if (brush.CanFreeze)
                brush.Freeze();
            return brush;
        }
        private Brush defaultErrorTypeBorderBrush;
        private Thickness? defaultErrorTypeBorderThickness;
        #region Properties

        public event EventHandler ErrorTypeValueChanged;
        public event EventHandler SolutionValueChanged;


        private cSupportCaseDataProvider dataProvider;
        public cSupportCaseDataProvider DataProvider
        {
            get => dataProvider; set
            {
                dataProvider = value;
                UpdateErrorTypeComboBox();
            }
        }

        #region Solution

        public string Solution
        {
            get { return (string)GetValue(SolutionProperty); }
            set { 
                SetValue(SolutionProperty, value);
            }
        }

        public static readonly DependencyProperty SolutionProperty =
            DependencyProperty.Register("Solution", typeof(string), typeof(CloseTicketDialog), new PropertyMetadata(string.Empty, OnSolutionPropertyChanged));
        private static void OnSolutionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = (CloseTicketDialog)d;
            control.SolutionValueChanged?.Invoke(control, EventArgs.Empty);
        }

        #endregion



        public ComboBoxItem SelectedErrorType
        {
            get { return (ComboBoxItem)GetValue(SelectedErrorTypeProperty); }
            set { SetValue(SelectedErrorTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedErrorType.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedErrorTypeProperty =
            DependencyProperty.Register("SelectedErrorType", typeof(ComboBoxItem), typeof(CloseTicketDialog), new PropertyMetadata(null, OnSelectedErrorTypeChanged));
        private static void OnSelectedErrorTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is CloseTicketDialog control))
                return;

            var newItem = e.NewValue as ComboBoxItem;
            bool hasError = newItem == null || newItem.Tag == null;

            if (control.ErrorTypeComboBox != null && !Equals(control.ErrorTypeComboBox.SelectedItem, newItem))
            {
                control.ErrorTypeComboBox.SelectedItem = newItem;
            }

            control.UpdateErrorTypeValidationState(hasError);
            control.ErrorTypeValueChanged?.Invoke(control, EventArgs.Empty);
        }


        #endregion

        public CloseTicketDialog()
        {
            InitializeComponent();
            defaultErrorTypeBorderBrush = ErrorTypeValidationBorder?.BorderBrush?.CloneCurrentValue();
            defaultErrorTypeBorderThickness = ErrorTypeValidationBorder?.BorderThickness;
        }

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

        private void UpdateErrorTypeComboBox()
        {
            try
            {
                if (DataProvider == null) return;

                var activityErrorTable = DataProvider.HealthCardDataHelper.HealthCardRawData.GetTableByName("M42Wpm-Pickup-ActivityErrorType", false);
                if (activityErrorTable == null) return;

                if (!activityErrorTable.Columns.TryGetValue("name", out var namesColumn) ||
                    !activityErrorTable.Columns.TryGetValue("position", out var positionsColumn) ||
                    !activityErrorTable.Columns.TryGetValue("hidden", out var hiddensColumn) ||
                    !activityErrorTable.Columns.TryGetValue("id", out var idsColumn)) return;

                var errorTypeListe = new List<Dictionary<string, object>>();

                for (int i = 0; i < idsColumn.Values.Count; i++)
                {
                    if (int.TryParse(positionsColumn.Values[i].ToString(), out int positionValue))
                    {
                        var eintrag = new Dictionary<string, object>
                {
                    { "ID", idsColumn.Values[i] },
                    { "DisplayName", namesColumn.Values[i] },
                    { "Hidden", Convert.ToBoolean(hiddensColumn.Values[i])},
                    { "Position", positionValue }
                };
                        errorTypeListe.Add(eintrag);
                    }
                }

                // Filtere die Liste, um nur nicht versteckte Elemente zu behalten
                errorTypeListe = errorTypeListe.Where(eintrag => !(bool)eintrag["Hidden"]).OrderBy(eintrag => (int)eintrag["Position"]).ToList();

                var editComboBox = ErrorTypeComboBox;
                editComboBox.Items.Clear();

                foreach (var listValue in errorTypeListe)
                {
                    editComboBox.Items.Add(new ComboBoxItem { Content = listValue["DisplayName"], Tag = listValue["ID"] });
                }
            }
            catch (Exception e)
            {
                LogException(e);
            }
        }
 
        private void DropDownOpened(object sender, EventArgs e)
        {
            try
            {
                if (!(sender is FrameworkElement senderElement))
                    return;

                var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
                cFocusInvoker.InvokeGotFocus(parentBorder, e);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void DropDownClosed(object sender, EventArgs e)
        {
            try
            {
                if (!(sender is FrameworkElement senderElement))
                    return;
                ErrorTypeValueChanged?.Invoke(this, EventArgs.Empty);
                var parentBorder = cUiElementHelper.GetFirstParentOfType<Border>(senderElement);
                cFocusInvoker.InvokeLostFocus(parentBorder, e);

                _ = Dispatcher.BeginInvoke((Action)(() =>
                {
                    try
                    {
                        var parentScrollViewer = cUiElementHelper.GetFirstParentOfType<ScrollViewer>(this);
                        Keyboard.ClearFocus();

                        if (parentScrollViewer != null)
                        {
                            parentScrollViewer.Focus();
                            Keyboard.Focus(parentScrollViewer);
                        }
                    }
                    catch (Exception exception)
                    {
                        LogException(exception);
                    }
                }), System.Windows.Threading.DispatcherPriority.Input);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        private void ErrorTypeComboBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Escape) { 
                DropDownClosed(sender, e);
            }
        }

        private void ErrorTypeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var selected = ErrorTypeComboBox?.SelectedItem as ComboBoxItem;

            if (!Equals(SelectedErrorType, selected))
            {
                SelectedErrorType = selected;
                return;
            }

            bool hasError = selected == null || selected.Tag == null;
            UpdateErrorTypeValidationState(hasError);
        }

        public void UpdateErrorTypeValidationState(bool hasError)
        {
            if (ErrorTypeValidationBorder == null)
                return;

            if (defaultErrorTypeBorderBrush == null)
                defaultErrorTypeBorderBrush = ErrorTypeValidationBorder.BorderBrush?.CloneCurrentValue();
            if (defaultErrorTypeBorderThickness == null)
                defaultErrorTypeBorderThickness = ErrorTypeValidationBorder.BorderThickness;

            ErrorTypeValidationBorder.BorderBrush = hasError ? ValidationBrush : defaultErrorTypeBorderBrush;
            ErrorTypeValidationBorder.BorderThickness = hasError ? new Thickness(1) : defaultErrorTypeBorderThickness ?? new Thickness(0);
        }
    }
}
