using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;
using MaterialIcons;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
using System.Reflection;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Enums;
using System.Windows.Media;

namespace FasdDesktopUi.Basics.Helper
{
    public class cUiElementHelper
    {
        public static FrameworkElement GetEditableControl(cEditableValueInformationBase editableValueInformation, bool isEditOnly, FrameworkElement parent, double? fontSize = null, FontWeight? fontWeight = null)
        {
            FrameworkElement output = null;
            var textBlockStyle = (Style)Application.Current.FindResource("DetailsPage.Widget.Title");
            var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");

            try
            {
                switch (editableValueInformation)
                {
                    case cEditValueInformationText editValueText:
                        output = GetEditTextBox(editableValueInformation.CurrentValue.ToString(), string.Empty, fontSize ?? 12, fontWeight ?? FontWeights.Normal, false, true);
                        break;
                    case cEditValueInformationSelection editValueSelection:
                        {
                            if (editValueSelection.SelectionValues is null || editValueSelection.SelectionValues?.Count <= 0)
                                return null;

                            ComboBox editComboBox = new ComboBox();
                            foreach (var listValue in editValueSelection.SelectionValues)
                            {
                                ComboBoxItem tempComboBoxItem = new ComboBoxItem() { Content = listValue.Value, Tag = listValue.Key };
                                editComboBox.Items.Add(tempComboBoxItem);
                            }

                            var currentSelectedValue = editValueSelection.SelectionValues.FirstOrDefault(value => value.Key?.Equals(editValueSelection.CurrentValue) ?? false);
                            editComboBox.SelectedIndex = editValueSelection.SelectionValues.IndexOf(currentSelectedValue);

                            editComboBox.DropDownOpened += (sender, e) => cFocusInvoker.InvokeGotFocus(parent, e);
                            editComboBox.DropDownClosed += (sender, e) => cFocusInvoker.InvokeLostFocus(parent, e);

                            output = editComboBox;

                            if (!isEditOnly)
                                break;

                            StackPanel tempStackPanel = new StackPanel();
                            TextBlock tempTextBlock = new TextBlock() { Text = editValueSelection.Description, Style = textBlockStyle };
                            tempStackPanel.Children.Add(tempTextBlock);
                            tempStackPanel.Children.Add(editComboBox);

                            output = tempStackPanel;
                        }
                        break;
                    default:
                        break;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private static FrameworkElement GetEditTextBox(string contentText, string placeHolderText, double fontSize, FontWeight fontWeight, bool isPrimaryContent, bool isEditOnly)
        {
            ScrollViewer output = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto };
            try
            {
                Grid mainGrid = new Grid();
                var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");
                var textBoxStylePrimary = (Style)Application.Current.FindResource("Customizable.Editable.TextBox.Background");
                var textBoxStyleEditOnly = (Style)Application.Current.FindResource("Customizable.Editable.TextBox.EditOnly");

                TextBlock placeHolderTextBlock = new TextBlock() { Text = placeHolderText, FontSize = fontSize, FontWeight = fontWeight, IsHitTestVisible = false, Opacity = 0.7, Margin = new Thickness(13, 16, 13, 14) };
                placeHolderTextBlock.SetResourceReference(TextBlock.ForegroundProperty, "FontColor.Menu.Categories");

                TextBox contentTextBox = new TextBox() { Text = contentText, FontSize = fontSize, FontWeight = fontWeight, Style = textBoxStyle };

                if (isPrimaryContent)
                    contentTextBox.Style = textBoxStylePrimary;

                if (isEditOnly)
                    contentTextBox.Style = textBoxStyleEditOnly;

                contentTextBox.TextChanged += (sender, e) => placeHolderTextBlock.Visibility = string.IsNullOrEmpty(contentTextBox.Text) ? Visibility.Visible : Visibility.Collapsed;

                AdaptableIcon editIcon = new AdaptableIcon() { SelectedMaterialIcon = MaterialIconType.ic_edit, HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top, Visibility = isEditOnly ? Visibility.Visible : Visibility.Hidden, BorderPadding = new Thickness(7.5, 7.5, 0, 7.5) };
                editIcon.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");

                mainGrid.Children.Add(contentTextBox);
                mainGrid.Children.Add(placeHolderTextBlock);
                mainGrid.Children.Add(editIcon);

                output.Content = mainGrid;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        public static bool DrawCustomizableContainerComponent(IContainerData data, FrameworkElement parentElement, out FrameworkElement createdControl, Action<(FrameworkElement valueControl, FrameworkElement editControl)> addEditableControls = null)
        {
            createdControl = null;
            try
            {
                var textBlockStyle = (Style)Application.Current.FindResource("DetailsPage.Widget.Title");
                var textBoxStyle = (Style)Application.Current.FindResource("Customizable.Editable.TextBox");

                switch (data)
                {
                    case cContainerIcon containerIconData:
                        {
                            enumInternIcons? internIcon = null;
                            enumInternGif? internGif = null;
                            MaterialIconType? materialIcon = null;


                            if (Enum.TryParse<enumInternIcons>(containerIconData.IconName, out var tempInternIcon))
                                internIcon = tempInternIcon;

                            if (Enum.TryParse<enumInternGif>(containerIconData.IconName, out var tempInternGif))
                                internGif = tempInternGif;

                            if (Enum.TryParse<MaterialIconType>(containerIconData.IconName, out var tempMaterialIcon))
                                materialIcon = tempMaterialIcon;

                            createdControl = new AdaptableIcon()
                            {
                                SelectedInternIcon = internIcon,
                                SelectedInternGif = internGif,
                                SelectedMaterialIcon = materialIcon,
                                ToolTip = containerIconData.ToolTipText,
                                BorderPadding = new Thickness(0),
                                IconHeight = 14,
                                IconWidth = 14,
                                Margin = new Thickness(0, 0, 5, 0)
                            };

                            string iconResourceName = "Color.Menu.Icon";
                            switch (containerIconData.HighlightColor)
                            {
                                case enumHighlightColor.blue:
                                    iconResourceName = "Color.Blue";
                                    break;
                                case enumHighlightColor.green:
                                    iconResourceName = "Color.Green";
                                    break;
                                case enumHighlightColor.orange:
                                    iconResourceName = "Color.Orange";
                                    break;
                                case enumHighlightColor.red:
                                    iconResourceName = "Color.Red";
                                    break;
                            }

                            if (createdControl is AdaptableIcon createdAdaptable)
                                createdAdaptable.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, iconResourceName);
                            break;
                        }
                    case cContainerPrimaryContent primaryContentData:
                        {
                            if (primaryContentData.Value is cContainerValue primaryContentValueData)
                            {
                                string contentText = primaryContentValueData.IsEditOnly ? string.Empty : primaryContentValueData.DisplayValue;
                                string placeHolderText = primaryContentValueData.IsEditOnly ? primaryContentValueData.DisplayValue : string.Empty;

                                createdControl = GetEditTextBox(contentText, placeHolderText, primaryContentValueData.FontSize, primaryContentValueData.FontWeight, true, primaryContentValueData.IsEditOnly);

                                if (primaryContentValueData.IsEditOnly)
                                    break;

                                if (primaryContentValueData.EditableValueInformation is null)
                                    break;

                                var editControl = GetEditableControl(primaryContentValueData.EditableValueInformation, true, parentElement, primaryContentValueData.FontSize, primaryContentValueData.FontWeight);
                                editControl.Visibility = Visibility.Collapsed;

                                Grid tempCreatedControl = new Grid();
                                tempCreatedControl.Children.Add(createdControl);
                                tempCreatedControl.Children.Add(editControl);
                                addEditableControls?.Invoke((createdControl, editControl));

                                createdControl = tempCreatedControl;
                            }
                            else
                            {
                                var tempCreatedControl = new Border()
                                {
                                    Padding = new Thickness(10),
                                    Margin = new Thickness(0, 5, 0, 5),
                                    CornerRadius = new CornerRadius(7.5)
                                };
                                tempCreatedControl.SetResourceReference(Control.BackgroundProperty, "BackgroundColor.DetailsPage.Widget.Title");
                                DrawCustomizableContainerComponent(primaryContentData.Value, parentElement, out var childElement, addEditableControls);
                                tempCreatedControl.Child = childElement;

                                createdControl = tempCreatedControl;
                            }
                            break;
                        }
                    case cContainerStackPanel stackPanelData:
                        {
                            var tempCreatedControl = new StackPanel() { Orientation = stackPanelData.Orientation };

                            foreach (var stackPanelElement in stackPanelData.StackPanelData)
                            {
                                bool wasAbleToDraw = DrawCustomizableContainerComponent(stackPanelElement, parentElement, out var childElement, addEditableControls);

                                if (!wasAbleToDraw)
                                    continue;

                                tempCreatedControl.Children.Add(childElement);
                            }

                            createdControl = tempCreatedControl;
                            break;
                        }
                    case cContainerValue containerValueData:
                        {
                            var tempCreatedControl = new Grid();

                            if (containerValueData.IsEditOnly)
                            {
                                createdControl = cUiElementHelper.GetEditableControl(containerValueData.EditableValueInformation, true, parentElement);
                                break;
                            }

                            var valueControl = new TextBlock()
                            {
                                Text = containerValueData.DisplayValue,
                                TextWrapping = TextWrapping.Wrap,
                                FontSize = containerValueData.FontSize,
                                FontWeight = containerValueData.FontWeight,
                                Margin = new Thickness(0, 0, 5, 0),
                                Style = textBlockStyle
                            };

                            if (!string.IsNullOrEmpty(containerValueData.Description))
                                valueControl.ToolTip = containerValueData.Description;

                            if (containerValueData.EditableValueInformation != null)
                            {
                                var editControl = cUiElementHelper.GetEditableControl(containerValueData.EditableValueInformation, false, parentElement, containerValueData.FontSize, containerValueData.FontWeight);
                                addEditableControls?.Invoke((valueControl, editControl));
                                tempCreatedControl.Children.Add(editControl);
                            }

                            tempCreatedControl.Children.Add(valueControl);
                            createdControl = tempCreatedControl;
                            break;
                        }
                }

                return createdControl != null;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return false;
        }

        public static void AddChildToFrameworkElement(FrameworkElement parentElement, FrameworkElement childElement)
        {
            try
            {
                if (parentElement is Panel parentPanel)
                    parentPanel.Children.Add(childElement);
                else if (parentElement is Decorator parentDecorator)
                    parentDecorator.Child = childElement;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        public static T GetFirstParentOfType<T>(FrameworkElement element) where T : UIElement
        {
            try
            {
                if (element.Parent is null)
                    return null;

                if (element.Parent is T parentElement)
                    return parentElement;

                if (element.Parent is FrameworkElement parentFrameworkElement)
                    return GetFirstParentOfType<T>(parentFrameworkElement);
            }
            catch (Exception E)
            {
                LogException(E);
            }
            return null;
        }

    }
}
