using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;

using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon.Enums;
using MaterialIcons;
using FasdDesktopUi.Basics.Helper;

namespace FasdDesktopUi.Pages.DetailsPage.UserControls
{
    public partial class DetailsPageStateContainer : UserControl
    {
        private readonly List<(FrameworkElement ValueControl, FrameworkElement EditControl)> EditableControls = new List<(FrameworkElement ValueControl, FrameworkElement EditControl)>();

        #region Properties

        public cContainerData ContainerData
        {
            get { return (cContainerData)GetValue(ContainerDataProperty); }
            set { SetValue(ContainerDataProperty, value); }
        }

        public static readonly DependencyProperty ContainerDataProperty =
            DependencyProperty.Register("ContainerData", typeof(cContainerData), typeof(DetailsPageStateContainer), new PropertyMetadata(null, new PropertyChangedCallback(ContainerDataChanged)));

        private static void ContainerDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is DetailsPageStateContainer _me))
                return;

            _me.EditableControls.Clear();
            _me.DrawContainerContent();
        }

        #endregion

        public DetailsPageStateContainer()
        {
            InitializeComponent();
        }

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

        private void DrawContainerContent()
        {
            try
            {
                if (ContainerData.IsMaximizable)
                    FullSizeButton.Visibility = Visibility.Visible;
                else
                    FullSizeButton.Visibility = Visibility.Collapsed;

                if(ContainerData.IsAddable)
                    AddButton.Visibility = Visibility.Visible;
                else
                    AddButton.Visibility = Visibility.Collapsed;

                foreach (var containerElement in ContainerData)
                {
                    cUiElementHelper.DrawCustomizableContainerComponent(containerElement, this, out var createdElement, EditableControls.Add);
                    MainStackPanel.Children.Add(createdElement);
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private string GetHtmlString(string maximizeValue, double fontSize = 14.0)
        {
            var output = maximizeValue;
            try
            {
                var backgroundColor = (SolidColorBrush)TryFindResource("BackgroundColor.DetailsPage.Widget.Title");
                var backgroundColorString = string.Empty;

                if (backgroundColor != null)
                    backgroundColorString = $"rgb({backgroundColor.Color.R}, {backgroundColor.Color.G}, {backgroundColor.Color.B} )";

                var foreGroundColor = (SolidColorBrush)TryFindResource("FontColor.DetailsPage.Widget");
                var foreGroundColorString = string.Empty;

                if (foreGroundColor != null)
                    foreGroundColorString = $"rgb({foreGroundColor.Color.R}, {foreGroundColor.Color.G}, {foreGroundColor.Color.B} )";

                string htmlPrefix = $"<html><head><meta charset=\"UTF-8\"></head><body style=\"background-color: {backgroundColorString}; color: {foreGroundColorString}; font-size: {fontSize}px; font-family: Calibri, sans-serif; overflow: auto\"><div>";
                string htmlSuffix = "</div></body></html>";

                output = htmlPrefix + maximizeValue + htmlSuffix;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return output;
        }

        private void DrawMaximizedControl(IContainerData containerDataEntry, FrameworkElement parentElement)
        {
            try
            {
                const double enlargementFactor = 1.5;

                FrameworkElement createdControl = null;
                switch (containerDataEntry)
                {
                    case cContainerValue containerValueData:
                        {
                            if (string.IsNullOrEmpty(containerValueData?.MaximizeValue))
                            {
                                createdControl = new TextBlock()
                                {
                                    Text = containerValueData.DisplayValue,
                                    TextWrapping = TextWrapping.Wrap,
                                    FontSize = containerValueData.FontSize * enlargementFactor,
                                    FontWeight = containerValueData.FontWeight,
                                    Margin = new Thickness(0, 0, 5, 0),
                                    Style = textBlockStyle
                                };

                                if (!string.IsNullOrEmpty(containerValueData.Description))
                                    createdControl.ToolTip = containerValueData.Description;
                            }
                            else
                            {
                                var webBrowser = new WebBrowser() { ClipToBounds = true };
                                webBrowser.SetValue(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Hidden);

                                string htmlControlString = GetHtmlString(containerValueData.MaximizeValue, containerValueData.FontSize * enlargementFactor);

                                webBrowser.NavigateToString(htmlControlString);

                                createdControl = new Border() { Child = webBrowser };

                                if (createdControl is Border createdBorder)
                                    createdBorder.SetResourceReference(BackgroundProperty, "BackgroundColor.DetailsPage.Widget.Title");
                            }

                            break;
                        }
                    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 * enlargementFactor,
                                IconWidth = 14 * enlargementFactor,
                                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 (parentElement is Grid parentGrid)
                                parentGrid.RowDefinitions.Last().Height = new GridLength(1, GridUnitType.Star);

                            createdControl = new Border()
                            {
                                Padding = new Thickness(10),
                                Margin = new Thickness(0, 5, 0, 5),
                                CornerRadius = new CornerRadius(7.5)
                            };

                            if (createdControl is Border createdBorder)
                                createdBorder.SetResourceReference(BackgroundProperty, "BackgroundColor.DetailsPage.Widget.Title");

                            DrawMaximizedControl(primaryContentData.Value, createdControl);
                            break;
                        }
                    case cContainerStackPanel stackPanelData:
                        {
                            createdControl = new StackPanel() { Orientation = stackPanelData.Orientation };

                            foreach (var stackPanelElement in stackPanelData.StackPanelData)
                            {
                                DrawMaximizedControl(stackPanelElement, createdControl);
                            }
                            break;
                        }
                }

                if (createdControl is null)
                    return;

                if (parentElement is Panel parentPanel)
                {
                    if (parentPanel is Grid parentGrid)
                        Grid.SetRow(createdControl, parentGrid.RowDefinitions.Count - 1);

                    parentPanel.Children.Add(createdControl);
                }
                else if (parentElement is Decorator parentDecorator)
                {
                    parentDecorator.Child = createdControl;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private Decorator GetMaximizedContainer()
        {
            Decorator output = null;

            try
            {
                output = new Border()
                {
                    CornerRadius = new CornerRadius(10),
                    Padding = new Thickness(22)
                };
                output.SetResourceReference(BackgroundProperty, "BackgroundColor.DetailsPage.Widget.Value");

                Grid grid = new Grid();
                output.Child = grid;

                AdaptableIcon closeIcon = new AdaptableIcon()
                {
                    HorizontalAlignment = HorizontalAlignment.Right,
                    SelectedInternIcon = enumInternIcons.window_close,
                    IconHeight = 35,
                    IconWidth = 35,
                    Margin = new Thickness(0, -10, 0, 0)
                };
                Panel.SetZIndex(closeIcon, 1);
                closeIcon.SetResourceReference(StyleProperty, "SettingsPage.Close.Icon");
                closeIcon.MouseLeftButtonUp += CloseIcon_MouseLeftButtonUp;
                closeIcon.TouchDown += CloseIcon_TouchDown;

                grid.Children.Add(closeIcon);

                foreach (var containerDataEntry in ContainerData)
                {
                    try
                    {
                        grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });
                        DrawMaximizedControl(containerDataEntry, grid);
                    }
                    catch (Exception E)
                    {
                        LogException(E);
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
            }

            return output;
        }


        #region FullSizeButton Click

        private void FullSizeButton_Click()
        {
            try
            {
                var maximizedContainer = GetMaximizedContainer();

                if (maximizedContainer != null)
                    RaiseEvent(new ContainerEventArgs(MaximizeContainerEvent, this, maximizedContainer));
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void FullSizeButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            FullSizeButton_Click();
        }

        private void FullSizeButton_TouchDown(object sender, TouchEventArgs e)
        {
            FullSizeButton_Click();
        }

        #endregion

        #region Styles

        Style textBlockStyle;


        private void SetStyles()
        {
            textBlockStyle = (Style)FindResource("DetailsPage.Widget.Title");
        }

        public void SetEditMode(bool isActive)
        {
            try
            {
                foreach (var editablePair in EditableControls)
                {
                    editablePair.ValueControl.Visibility = isActive ? Visibility.Collapsed : Visibility.Visible;
                    editablePair.EditControl.Visibility = isActive ? Visibility.Visible : Visibility.Collapsed;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        #region Events

        #region Full Size Events

        public class ContainerEventArgs : RoutedEventArgs
        {
            public Decorator MaximizedControl { get; private set; }

            public ContainerEventArgs(RoutedEvent routedEvent, object source, Decorator maximizedControl) : base(routedEvent, source)
            {
                MaximizedControl = maximizedControl;
            }
        }

        public delegate void ContainerEventHandlerDelegate(object sender, ContainerEventArgs args);

        public static readonly RoutedEvent MaximizeContainerEvent = EventManager.RegisterRoutedEvent("MaximizeContainer", RoutingStrategy.Bubble, typeof(ContainerEventHandlerDelegate), typeof(DetailsPageStateContainer));

        public event RoutedEventHandler MaximizeContainer
        {
            add { AddHandler(MaximizeContainerEvent, value); }
            remove { RemoveHandler(MaximizeContainerEvent, value); }
        }

        #endregion

        #region Close Full Size Events

        public static readonly RoutedEvent CloseMaximizedContainerEvent = EventManager.RegisterRoutedEvent("CloseMaximizedContainer", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageStateContainer));

        public event RoutedEventHandler CloseMaximizedContainer
        {
            add { AddHandler(CloseMaximizedContainerEvent, value); }
            remove { RemoveHandler(CloseMaximizedContainerEvent, value); }
        }

        private void CloseIcon_Click()
        {

            try
            {
                RaiseEvent(new RoutedEventArgs(CloseMaximizedContainerEvent));
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void CloseIcon_TouchDown(object sender, TouchEventArgs e)
        {
            CloseIcon_Click();
        }

        private void CloseIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            CloseIcon_Click();
        }

        #endregion

        #endregion
    }
}
