using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using FasdDesktopUi.Basics;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Pages.DetailsPage.Models;

using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Pages.DetailsPage.UserControls
{
    public partial class DetailsPageDataHistoryCollection : UserControl
    {
        #region Properties

        public cSupportCaseDataProvider DataProvider { get; set; }

        #region DetailsGeometry DependencyProperty

        private static bool DidGeometryDataChanged(DependencyPropertyChangedEventArgs e)
        {
            bool didGeometryChange = false;

            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (e.NewValue != null && e.OldValue != null)
                {
                    var newValue = e.NewValue as DetailsPageDataHistoryCollectionGeometryModel;
                    var oldValue = e.OldValue as DetailsPageDataHistoryCollectionGeometryModel;

                    didGeometryChange = newValue.ColumnCount != oldValue.ColumnCount || didGeometryChange;

                    var oldValueSubtitleEnumerator = oldValue.SubtitleCount.GetEnumerator();
                    foreach (var subtitleCount in newValue.SubtitleCount)
                    {
                        if (oldValueSubtitleEnumerator.MoveNext())
                        {
                            didGeometryChange = subtitleCount != oldValueSubtitleEnumerator.Current || didGeometryChange;
                        }
                        else
                        {
                            didGeometryChange = true;
                        }
                    }
                }
                else
                {
                    didGeometryChange = true;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return didGeometryChange;
        }

        private static void GeometryChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (DidGeometryDataChanged(e) is false)
                return;

            var _me = d as DetailsPageDataHistoryCollection;
            _me.InitializeCollectionGeometry();
        }

        public static readonly DependencyProperty DetailsGeometryProperty =
            DependencyProperty.Register("DetailsGeometry", typeof(DetailsPageDataHistoryCollectionGeometryModel), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(new DetailsPageDataHistoryCollectionGeometryModel(), new PropertyChangedCallback(GeometryChangedCallback)));

        public DetailsPageDataHistoryCollectionGeometryModel DetailsGeometry
        {
            get { return (DetailsPageDataHistoryCollectionGeometryModel)GetValue(DetailsGeometryProperty); }
            set { SetValue(DetailsGeometryProperty, value); }
        }

        #endregion

        #region HistoryDataList DependencyProperty

        static void RefreshDataCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is DetailsPageDataHistoryCollection _me)
            {
                _me.UpdateDetailsCollection();
                _me.RefreshData();
            }
        }

        public static readonly DependencyProperty HistoryDataListProperty =
            DependencyProperty.Register("HistoryDataList", typeof(cDetailsPageDataHistoryDataModel), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(new cDetailsPageDataHistoryDataModel(), new PropertyChangedCallback(RefreshDataCallback)));

        public cDetailsPageDataHistoryDataModel HistoryDataList
        {
            get { return (cDetailsPageDataHistoryDataModel)GetValue(HistoryDataListProperty); }
            set { SetValue(HistoryDataListProperty, value); }
        }

        #endregion

        #region ShownValueColumnsCount DependencyProperty

        public static readonly DependencyProperty ShownValueColumnsCountProperty =
            DependencyProperty.Register("ShownValueColumnsCount", typeof(int), typeof(DetailsPageDataHistoryCollection), new PropertyMetadata(5));

        public int ShownValueColumnsCount
        {
            get { return (int)GetValue(ShownValueColumnsCountProperty); }
            set { SetValue(ShownValueColumnsCountProperty, value); }
        }
        #endregion

        #endregion

        public DetailsPageDataHistoryCollection()
        {
            InitializeComponent();
            AddCustomEventHandlers();
        }

        private void AddCustomEventHandlers()
        {
            AddHandler(DetailsPageDataHistoryValueColumn.StatusBorderClickedEvent, new RoutedEventHandler(ChangedVerticalCollapseEvent));
            AddHandler(DetailsPageDataHistoryTitleColumn.StatusBorderClickedEvent, new RoutedEventHandler(ChangedVerticalCollapseEvent));
        }

        #region SetUpControls

        #region Control Lists

        public readonly List<DetailsPageDataHistorySection> HistorySectionControls = new List<DetailsPageDataHistorySection>();

        #endregion

        #region SetUp/Initialize Functions

        private delegate void DelegateFunction();

        private void InitializeCollectionGeometry()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (DesignerProperties.GetIsInDesignMode(this) || DetailsGeometry == null)
                    return;

                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Background, new DelegateFunction(() =>
                {
                    DataHistoryCollectionStackPanel.Children.Clear();
                    HistorySectionControls.Clear();

                    for (int i = 0; i < DetailsGeometry.SubtitleCount.Count; i++)
                    {
                        DetailsPageDataHistorySection historySectionToCreate = new DetailsPageDataHistorySection() { ColumnCount = DetailsGeometry.ColumnCount, SubtitleCount = DetailsGeometry.SubtitleCount[i], Margin = new Thickness(0, 0, 0, 10) };
                        historySectionToCreate.HistoryValueScrollViewer.ScrollChanged += HistoryValueScrollViewer_ScrollChanged;
                        DataHistoryCollectionStackPanel.Children.Add(historySectionToCreate);
                        HistorySectionControls.Add(historySectionToCreate);
                    }

                }));
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void HistoryValueScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            foreach (var historyControl in HistorySectionControls)
            {
                historyControl.HistoryValueScrollViewer.ScrollToHorizontalOffset(e.HorizontalOffset);
            }
        }

        public void ToggleHorizontalCollapseHistory(bool isHorizontalVisible)
        {
            HistorySectionControls.ForEach(historyControl => historyControl.IsHorizontalCollapsed = !isHorizontalVisible);
        }

        #endregion

        #endregion

        #region Update Controls

        private void UpdateDetailsCollection()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (HistoryDataList == null)
                    return;

                UpdateHistorySections();
                UpdateColumnWidths();
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        private void UpdateHistorySections()
        {
            try
            {
                int missingDataSections = HistoryDataList.Count - HistorySectionControls.Count;
                if (missingDataSections > 0)
                {
                    for (int i = 0; i < missingDataSections; i++)
                    {
                        DetailsPageDataHistorySection historySectionToCreate = new DetailsPageDataHistorySection() { ColumnCount = DetailsGeometry.ColumnCount, SubtitleCount = int.MinValue, Margin = new Thickness(0, 0, 0, 10) };
                        historySectionToCreate.HistoryValueScrollViewer.ScrollChanged += HistoryValueScrollViewer_ScrollChanged;
                        DataHistoryCollectionStackPanel.Children.Add(historySectionToCreate);
                        HistorySectionControls.Add(historySectionToCreate);
                    }
                }
                else if (missingDataSections < 0 && HistorySectionControls.Count + missingDataSections >= 0)
                {
                    var categoriesToHide = HistorySectionControls.Skip(HistorySectionControls.Count + missingDataSections);

                    foreach (var categoryToHide in categoriesToHide)
                    {
                        categoryToHide.Visibility = Visibility.Collapsed;
                    }
                }

                HistorySectionControls.GetRange(0, HistoryDataList.Count).ForEach(section => section.Visibility = Visibility.Visible);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void ChangedVerticalCollapseEvent(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!(e.OriginalSource is FrameworkElement senderFrameworkElement))
                    return;

                if (!(senderFrameworkElement.Tag is DetailsPageDataHistorySection senderHistorySection))
                    return;

                if (senderHistorySection.IsVerticalExpandLocked)
                    return;

                bool tempExpandStatus = senderHistorySection.IsVerticalExpanded;

                foreach (var historySection in HistorySectionControls)
                {
                    if (!historySection.IsVerticalExpandLocked)
                        historySection.IsVerticalExpanded = false;
                }

                if (!tempExpandStatus)
                    VerticalUncollapseDataHistory(senderHistorySection);
                else
                    senderHistorySection.IsVerticalExpanded = !tempExpandStatus;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void UpdateColumnWidths()
        {
            try
            {
                const int maxValueColumnWidth = 140;
                double titleColumnWidth = 50;
                double valueColumnWidth = 50;

                foreach (var historyData in HistoryDataList)
                {
                    double tempTitleColumnWidth = GetTitleColumnWidth(historyData);
                    double tempValueColumnWidth = GetValueColumnWidth(historyData);

                    titleColumnWidth = tempTitleColumnWidth > titleColumnWidth ? tempTitleColumnWidth : titleColumnWidth;
                    valueColumnWidth = tempValueColumnWidth > valueColumnWidth ? tempValueColumnWidth : valueColumnWidth;
                }

                valueColumnWidth = Math.Min(valueColumnWidth, maxValueColumnWidth);

                foreach (var historyData in HistoryDataList)
                {
                    historyData.TitleColumnWidth = titleColumnWidth + 15;
                    historyData.ValueColumnWidth = valueColumnWidth + 10;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        #region RefreshData

        private void RefreshData()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (HistoryDataList is null || HistoryDataList.Count == 0)
                {
                    Visibility = Visibility.Collapsed;
                    return;
                }

                Visibility = Visibility.Visible;

                var DataEnumerator = HistoryDataList.GetEnumerator();
                foreach (var Entry in HistorySectionControls)
                {
                    if (DataEnumerator.MoveNext())
                    {
                        var Data = DataEnumerator.Current;
                        Entry.ShownValueColumnsCount = this.ShownValueColumnsCount;
                        //Entry.Visibility = Visibility.Visible;
                        //Entry.Visibility = Data?.TitleColumn.ColumnValues.Count <= 0 ? Visibility.Collapsed : Visibility.Visible;
                        //    && Data?.ValueColumns.Any(column => column.IsLoading) == false
                        //    && Data?.ValueColumns.Any(column => column.ColumnValues.Any(columnValue => columnValue.IsLoading)) == false ? Visibility.Collapsed : Visibility.Visible;
                        Entry.HistoryData = Data;
                    }
                    else
                    {
                        //Entry.Visibility = Visibility.Collapsed;
                        Entry.HistoryData = null;
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        #endregion

        #region UpdateData

        public void UpdateHistory(cDetailsPageDataHistoryDataModel historyData)
        {
            try
            {
                if (HistoryDataList is null || HistoryDataList.Count == 0)
                {
                    Visibility = Visibility.Collapsed;
                    return;
                }

                Visibility = Visibility.Visible;
                var historyDataEnumerator = HistoryDataList.GetEnumerator();

                for (int i = 0; i < historyData.Count; i++)
                {
                    var historyCategory = historyData[i];

                    historyDataEnumerator.MoveNext();

                    var currentHistoryData = historyDataEnumerator.Current;

                    if (DidHistoryCategoryChange(currentHistoryData, historyCategory))
                        HistorySectionControls[i]?.UpdateHistoryData(historyCategory);
                }

                HistoryDataList = historyData;
                UpdateColumnWidths();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private bool DidHistoryCategoryChange(cDetailsPageDataHistoryCategoryDataModel oldValue, cDetailsPageDataHistoryCategoryDataModel newValue)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (oldValue is null || newValue is null)
                    return true;

                if (oldValue.ValueColumns.Count != newValue.ValueColumns.Count)
                    return true;

                var newValueColumnEnumeator = newValue.ValueColumns.GetEnumerator();

                foreach (var oldValueColumn in oldValue.ValueColumns)
                {
                    if (!newValueColumnEnumeator.MoveNext())
                        continue;

                    var currentNewValueColumn = newValueColumnEnumeator.Current;
                    var newValueColumnValueEnumerator = currentNewValueColumn.ColumnValues.GetEnumerator();

                    foreach (var oldCellValue in oldValueColumn.ColumnValues)
                    {
                        var valueRowIndex = oldValueColumn.ColumnValues.IndexOf(oldCellValue);

                        if (!newValueColumnValueEnumerator.MoveNext())
                            continue;

                        if (oldCellValue.Content.Equals(newValueColumnValueEnumerator.Current.Content) == false)
                            return true;
                    }
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return false;
        }

        #endregion

        #region StyleDefinitions

        private Style titleColumnOverViewTitleStyle;
        private Style titleColumnMainTitleStyle;
        private Style titleCoumnSubTitleStyle;

        private void SetStyles()
        {
            titleColumnOverViewTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.OverviewTitle");
            titleColumnMainTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.MainTitle");
            titleCoumnSubTitleStyle = (Style)FindResource("DetailsPage.DataHistory.TitleColumn.SubTitle");
        }

        private static Size MeasureStringSize(string stringToMeasure, Control controlOfText)
        {
            var formattedText = new FormattedText(
                stringToMeasure,
                CultureInfo.CurrentCulture,
                FlowDirection.LeftToRight,
                new Typeface(controlOfText.FontFamily, controlOfText.FontStyle, controlOfText.FontWeight, controlOfText.FontStretch),
                controlOfText.FontSize,
                Brushes.Black,
                new NumberSubstitution(),
                1);

            return new Size(formattedText.Width, formattedText.Height);
        }

        private double GetTitleColumnWidth(cDetailsPageDataHistoryCategoryDataModel detailsData)
        {
            double maxTitleLength = MeasureStringSize(detailsData.TitleColumn.Content, new TextBox { Style = titleColumnOverViewTitleStyle }).Width + 90;

            foreach (var subtitle in detailsData.TitleColumn.ColumnValues)
            {
                Style subtitleStyle;

                switch (subtitle.PresentationStyle)
                {
                    case enumHistoryTitleType.value:
                        subtitleStyle = titleColumnMainTitleStyle;
                        break;
                    case enumHistoryTitleType.subValue:
                        subtitleStyle = titleCoumnSubTitleStyle;
                        break;
                    default:
                        subtitleStyle = titleColumnMainTitleStyle;
                        break;
                }

                double subtitleLength = MeasureStringSize(subtitle.Content, new TextBox { Style = subtitleStyle }).Width;
                maxTitleLength = maxTitleLength < subtitleLength ? subtitleLength + 70 : maxTitleLength;
            }

            return maxTitleLength;
        }

        private double GetValueColumnWidth(cDetailsPageDataHistoryCategoryDataModel detailsData)
        {
            double maxValueWidth = 55; //55 to set MinWidth

            foreach (var valueColumn in detailsData.ValueColumns)
            {
                foreach (var value in valueColumn.ColumnValues)
                {
                    var valueSize = MeasureStringSize(value.Content, new Control() { Style = titleColumnOverViewTitleStyle });

                    maxValueWidth = valueSize.Width > maxValueWidth ? valueSize.Width : maxValueWidth;
                }
            }

            return maxValueWidth + 30; //+30 to include functionmarker width
        }

        #endregion

        #region Event Methods

        #region UserControl

        private void UserControl_Initialized(object sender, EventArgs e)
        {
            SetStyles();
        }

        #endregion

        #region Collapse

        #region Vertical Uncollapse Specific DataHistory

        public void VerticalUncollapseDataHistory(DetailsPageDataHistorySection historySection)
        {
            try
            {
                var historyIndex = DataHistoryCollectionStackPanel.Children.IndexOf(historySection);
                VerticalUncollapseDataHistory(historyIndex);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        public void VerticalUncollapseDataHistory(int historyIndex)
        {
            try
            {
                if (historyIndex >= DataHistoryCollectionStackPanel.Children.Count)
                    return;

                HistorySectionControls.ForEach(historyControl =>
                {
                    if (!historyControl.IsVerticalExpandLocked)
                        historyControl.IsVerticalExpanded = false;
                });

                (DataHistoryCollectionStackPanel.Children[historyIndex] as DetailsPageDataHistorySection).IsVerticalExpanded = true;

                var _h = Dispatcher.Invoke(async () =>
                {
                    await Task.Delay(1);
                    var position = (DataHistoryCollectionStackPanel.Children[historyIndex] as DetailsPageDataHistorySection).TranslatePoint(new Point(0, 0), DataHistoryCollectionStackPanel);
                    DetailsCollectionScrollViewer.ScrollToVerticalOffset(position.Y);
                });
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        #region Vertical Collapse Details

        public void ToggleVerticalCollapseDetails(bool collapse)
        {
            try
            {
                foreach (var detail in HistorySectionControls)
                {
                    if (detail.IsVerticalExpandLocked)
                        continue;

                    detail.IsVerticalExpanded = !collapse;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }


        private void CollapseButton_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ToggleVerticalCollapseDetails(true);
        }

        private void CollapseButton_TouchDown(object sender, TouchEventArgs e)
        {
            ToggleVerticalCollapseDetails(true);
        }

        private void UnCollapseButton_MouseUp(object sender, MouseButtonEventArgs e)
        {
            ToggleVerticalCollapseDetails(false);
        }
        private void UnCollapseButton_TouchDown(object sender, TouchEventArgs e)
        {
            ToggleVerticalCollapseDetails(false);
        }

        #endregion

        #endregion

        private void DetailsCollectionScrollViewer_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        #endregion
    }
}
