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 System.Globalization;
using System.Reflection;

using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UserControls;
using FasdDesktopUi.Pages.DetailsPage.Models;
using FasdDesktopUi.Basics.UserControls.AdaptableIcon;

using C4IT.MultiLanguage;
using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon.Enums;
using C4IT.Logging;
using static C4IT.FASD.Base.cHealthCardTranslator;
using FasdDesktopUi.Basics;

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

        public List<int> AggregateRowIndexes { get; set; }
        public double ColumnWidth { get; set; } = 50;

        #region SubtitleCount DependencyProperty

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

            _me.ClearControls();
            _me.InitializeValueControls((int)e.NewValue);
        }


        public static readonly DependencyProperty SubtitleCountProperty =
            DependencyProperty.Register("SubtitleCount", typeof(int), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(1, new PropertyChangedCallback(SubtitleCountChangedCallback)));

        public int SubtitleCount
        {
            get { return (int)GetValue(SubtitleCountProperty); }
            set { SetValue(SubtitleCountProperty, value); }
        }

        #endregion

        #region ColumnValues DependencyProperty

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

            var updatedColumnValues = (DetailsPageDataHistoryColumnModel)e.NewValue;

            _me.UpdateColumnSize(updatedColumnValues.ColumnValues.Count - _me.MainGrid.RowDefinitions.Count);
            _me.RefreshColumnHeader(updatedColumnValues.Content);
            _me.RefreshColumnStatusIcon(updatedColumnValues.HighlightColor);
            _me.RefreshValueSection(updatedColumnValues);
        }

        public static readonly DependencyProperty ColumnValuesProperty =
            DependencyProperty.Register("ColumnValues", typeof(DetailsPageDataHistoryColumnModel), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(new DetailsPageDataHistoryColumnModel(), new PropertyChangedCallback(ColumnValuesChangedCallback)));

        public DetailsPageDataHistoryColumnModel ColumnValues
        {
            get { return (DetailsPageDataHistoryColumnModel)GetValue(ColumnValuesProperty); }
            set { SetValue(ColumnValuesProperty, value); }
        }

        #endregion

        #region ValueRecommendations DependencyProperty

        public static readonly DependencyProperty ValueRecommendationsProperty =
            DependencyProperty.Register("ValueRecommendations", typeof(List<cRecommendationDataModel>), typeof(DetailsPageDataHistoryValueColumn), new PropertyMetadata(new List<cRecommendationDataModel>()));

        public List<cRecommendationDataModel> ValueRecommendations
        {
            get { return (List<cRecommendationDataModel>)GetValue(ValueRecommendationsProperty); }
            set { SetValue(ValueRecommendationsProperty, value); }
        }

        #endregion

        #endregion

        #region Controls

        private readonly List<FrameworkElement> ValueControls = new List<FrameworkElement>();
        private readonly List<FunctionMarker> FunctionMarkers = new List<FunctionMarker>();

        #endregion

        private void ClearControls()
        {
            try
            {
                foreach (var functionMarker in FunctionMarkers)
                {
                    if (functionMarker.Parent is FrameworkElement functionMarkerParent)
                        MainGrid.Children.Remove(functionMarkerParent);
                }

                ValueControls.Clear();
                FunctionMarkers.Clear();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void UpdateBorderThresholdValues(Border border, cDataHistoryValueModel valueInfo)
        {
            try
            {
                switch (valueInfo?.HighlightColor)
                {
                    case enumHighlightColor.none:
                        border.ClearValue(TagProperty);
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder");
                        break;
                    case enumHighlightColor.blue:
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Blue");
                        break;
                    case enumHighlightColor.green:
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Green");
                        break;
                    case enumHighlightColor.orange:
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Orange");
                        break;
                    case enumHighlightColor.red:
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder.Red");
                        break;
                    default:
                        border.ClearValue(TagProperty);
                        border.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder");
                        break;
                };

                border.Tag = valueInfo?.ThresholdValues;
            }
            catch (Exception E)
            {
                LogException(E);
            }
    
        }

        #region Initialize Controls

        private void InitializeValueRow(int rowIndex)
        {
            MainGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(35) });

            DockPanel valueDockPanel = new DockPanel() { Margin = new Thickness(-19, 0, 0, 0) };
            Border valueBorder = new Border() { Style = dataHistoryValueBorderStyle };

#if isNewFeature
            valueBorder.ToolTip = (ToolTip)FindResource("Tooltip.Treshold");
            valueBorder.ToolTipOpening += TresholdToolTipEventHandler;
#endif

            TextBlock valueTextBlock = new TextBlock();

            valueBorder.Child = valueTextBlock;
            ValueControls.Add(valueTextBlock);
            valueDockPanel.Children.Add(valueBorder);

            var valueFunctionMarker = FunctionMarker.SetUpFunctionMarker(valueDockPanel, new FunctionMarker.FunctionMarkerClick(FunctionMarker_Click));
            FunctionMarkers.Add(valueFunctionMarker);
            DockPanel.SetDock(valueBorder, Dock.Left);

            Grid.SetRow(valueDockPanel, rowIndex);
            MainGrid.Children.Add(valueDockPanel);
        }


        public void TresholdToolTipEventHandler(object sender, ToolTipEventArgs e)
        {
#if isNewFeature
            try
            {
                if (!(sender is Border _b) || !(_b.Tag is cStateThresholdValues _v) || !(_b.ToolTip is StatusTreshholdTooltip _t))
                {
                    e.Handled = true;
                    return;
                }

                cUtility.FillTresholdToolTip(_v, _t);

            }
            catch (Exception E)
            {
                LogException(E);
            }
#endif
        }

        private void InitializeValueControls(int valueCount)
        {
            for (int i = 0; i < valueCount; i++)
            {
                try
                {
                    InitializeValueRow(i);
                }
                catch (Exception E)
                {
                    LogException(E);
                }
            }
        }

        private void FunctionMarker_Click(object sender)
        {
            if (!(sender is FrameworkElement FE))
                return;

            if (!(FE.Tag is cDataHistoryValueModel HistoryValue))
                return;

            if (HistoryValue.UiAction == null)
                return;

            cUiActionBase.RaiseEvent(HistoryValue.UiAction, this, this);
        }

        #endregion

        #region Update Controls

        private void UpdateColumnSize(int rowsToAdd)
        {
            if (rowsToAdd > 0)
            {
                int rowIndex = MainGrid.RowDefinitions.Count;

                for (int i = rowIndex; i < rowsToAdd + rowIndex; i++)
                {
                    InitializeValueRow(i);
                }
            }
            else
            {
                MainGrid.RowDefinitions.ToList().ForEach(rowDefinitions => rowDefinitions.Height = new GridLength(35));

                var reversedRowList = MainGrid.RowDefinitions.Reverse().ToList();
                for (int i = 0; i < Math.Abs(rowsToAdd); i++)
                {
                    reversedRowList[i].Height = new GridLength(0);
                }
            }
        }

        #endregion

        #region Refresh Values

        private void RefreshColumnHeader(string columnHeader)
        {
            string headerContent;

            if (int.TryParse(columnHeader, out int dayIndex))
            {
                CultureInfo culture = new CultureInfo(cMultiLanguageSupport.CurrentLanguage);
                string customDateFormat = cMultiLanguageSupport.GetItem("Global.Date.Format.ShortDateWithDay", "ddd. dd.MM.");
                headerContent = dayIndex == 0 ? cMultiLanguageSupport.GetItem("Global.Date.Today", DateTime.Now.ToString(customDateFormat, culture)) : DateTime.Today.AddDays(-dayIndex).ToString(customDateFormat, culture);
            }
            else
                headerContent = columnHeader;

            ColumnHeaderTextBlock.Text = headerContent;
        }

        private void RefreshColumnStatusIcon(enumHighlightColor? statusColor)
        {
            ColumnStatusIcon.IconWidth = 25;

            if (ColumnValues.ColumnValues.Any(value => value.IsLoading && value.Content == "-") && statusColor != enumHighlightColor.red)
            {
                //todo: replace loading icon
                ColumnStatusIcon.SelectedInternIcon = enumInternIcons.menuBar_more;
                ColumnStatusIcon.PrimaryIconColor = iconColor;
                return;
            }

            switch (statusColor)
            {
                case enumHighlightColor.blue:
                    ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_info;
                    ColumnStatusIcon.PrimaryIconColor = blueBrush;
                    ColumnStatusIcon.SecondaryIconColor = Brushes.White;
                    break;
                case enumHighlightColor.green:
                    ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_good;
                    ColumnStatusIcon.PrimaryIconColor = greenBrush;
                    ColumnStatusIcon.SecondaryIconColor = Brushes.White;
                    break;
                case enumHighlightColor.orange:
                    ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_danger;
                    ColumnStatusIcon.PrimaryIconColor = orangeBrush;
                    ColumnStatusIcon.SecondaryIconColor = Brushes.White;
                    break;
                case enumHighlightColor.red:
                    ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_bad;
                    ColumnStatusIcon.PrimaryIconColor = redBrush;
                    ColumnStatusIcon.SecondaryIconColor = Brushes.White;
                    break;
                default:
                    ColumnStatusIcon.SelectedInternIcon = enumInternIcons.status_empty;
                    ColumnStatusIcon.SetResourceReference(AdaptableIcon.PrimaryIconColorProperty, "Color.SoftContrast");
                    ColumnStatusIcon.IconWidth = 15;
                    break;
            }
        }

        private void RefreshColumnValues(DetailsPageDataHistoryColumnModel columnData)
        {
            try
            {
                var valueRowEnumerator = columnData.ColumnValues.GetEnumerator();
                int tempTitleRowIndex = 0;

                foreach (var valueRow in ValueControls)
                {
                    if (!valueRowEnumerator.MoveNext())
                        continue;

                    if (AggregateRowIndexes != null && AggregateRowIndexes.Contains(tempTitleRowIndex))
                    {
                        var valueRowData = valueRowEnumerator.Current;

                        if (!(valueRow is TextBlock valueRowTextBlock))
                            continue;

                        valueRowTextBlock.Style = dataHistoryValueAggregateStyle;
                        valueRowTextBlock.Text = valueRowData.Content;
#if !isNewFeature
                        valueRowTextBlock.ToolTip = valueRowData.ContentDescription;
#endif


                        if (valueRow.Parent is FrameworkElement valueRowParent)
                        {
                            valueRowParent.ClearValue(TagProperty);
                            valueRowParent.SetResourceReference(StyleProperty, "DetailsPage.DataHistory.ValueBorder");
                        }

                        switch (valueRowData.HighlightColor)
                        {
                            case enumHighlightColor.none:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
                                break;
                            case enumHighlightColor.blue:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Blue");
                                break;
                            case enumHighlightColor.green:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Green");
                                break;
                            case enumHighlightColor.orange:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Orange");
                                break;
                            case enumHighlightColor.red:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "Color.Red");
                                break;
                            default:
                                valueRowTextBlock.SetResourceReference(ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
                                break;
                        };

                        valueRow.Visibility = Visibility.Visible;
                        valueRow.Opacity = 1;
                    }
                    else
                    {
                        var valueRowData = valueRowEnumerator.Current;

                        if (!(valueRow is TextBlock valueRowTextBlock))
                            continue;

                        valueRowTextBlock.ClearValue(ForegroundProperty);
                        valueRowTextBlock.Style = dataHistoryValueStyle;
                        valueRowTextBlock.Text = valueRowData.Content;

#if !isNewFeature
                        valueRowTextBlock.ToolTip = valueRowData.ContentDescription;
#endif

                        Style borderStyle = new Style() { BasedOn = dataHistoryValueBorderStyle };

                        if (valueRow.Parent is Border valueRowParentBorder)
                            UpdateBorderThresholdValues(valueRowParentBorder, valueRowData);

                        valueRow.Visibility = Visibility.Visible;
                        valueRow.Opacity = 1;

                        if (valueRowData.Content == "-" && valueRowData.IsLoading)
                        {
                            valueRowTextBlock.Text = "...";
                        }
                    }

                    tempTitleRowIndex++;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
            }
        }

        private void RefreshFunctionMarker(DetailsPageDataHistoryColumnModel columnData)
        {
            var valueRowEnumerator = columnData.ColumnValues.GetEnumerator();

            foreach (var valueRow in FunctionMarkers)
            {
                if (valueRowEnumerator.MoveNext())
                {
                    var valueRowData = valueRowEnumerator.Current;

                    if (valueRowData.UiAction != null)
                    {
                        valueRow.Tag = valueRowData;

                        var tempToolTip = valueRowData.UiAction.Name;
                        if (!string.IsNullOrEmpty(valueRowData.UiAction.Description))
                            tempToolTip += ": \n" + valueRowData.UiAction.Description;

                        valueRow.ToolTip = tempToolTip;
                        valueRow.Visibility = Visibility.Visible;
                    }
                    else
                        valueRow.Visibility = Visibility.Hidden;
                }
            }
        }

        private void RefreshValueSection(DetailsPageDataHistoryColumnModel columnData)
        {
            RefreshColumnValues(columnData);
            RefreshFunctionMarker(columnData);
        }

        #endregion

        #region UpdateValues

        private bool DidCellValueChange(cDataHistoryValueModel oldData, cDataHistoryValueModel newData)
        {
            try
            {
                if (oldData is null || newData is null)
                    return true;

                if (oldData.Content.Equals(newData.Content) == false || oldData.IsLoading != newData.IsLoading)
                    return true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
            }

            return false;
        }

        public void UpdateHistoryValues(DetailsPageDataHistoryColumnModel columnData)
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (columnData?.ColumnValues is null)
                    return;

                for (int i = 0; i < columnData.ColumnValues.Count; i++)
                {
                    var oldValue = ColumnValues?.ColumnValues?.Count > i ? ColumnValues.ColumnValues[i] : null;
                    var newValue = columnData.ColumnValues[i];

                    if (ValueControls.Count < i)
                        continue;

                    if (DidCellValueChange(oldValue, newValue))
                    {
                        if (ValueControls[i] is TextBlock valueTextBlock)
                        {
                            valueTextBlock.Text = newValue?.Content;

#if !isNewFeature
                            valueTextBlock.ToolTip = newValue?.Content;
#endif

                            valueTextBlock.Visibility = Visibility.Visible;
                        }

                        if (ValueControls[i].Parent is Border valueBorder)
                        {
                            UpdateBorderThresholdValues(valueBorder, newValue);
                        }
                    }

                    if (newValue.Content.Equals("Ø"))
                    {
                        if (ValueControls[i] is TextBlock aggregateTextBlock)
                            switch (newValue.HighlightColor)
                            {
                                case enumHighlightColor.green:
                                    aggregateTextBlock.Foreground = greenBrush;
                                    break;
                                case enumHighlightColor.orange:
                                    aggregateTextBlock.Foreground = orangeBrush;
                                    break;
                                case enumHighlightColor.red:
                                    aggregateTextBlock.Foreground = redBrush;
                                    break;
                                default:
                                    break;
                            }
                    }
                }

                if (ColumnValues is null)
                    ColumnValues = new DetailsPageDataHistoryColumnModel();

                ColumnValues.ColumnValues = columnData.ColumnValues;
                RefreshColumnStatusIcon(columnData.HighlightColor);
                Visibility = Visibility.Visible;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        #endregion

        public DetailsPageDataHistoryValueColumn()
        {
            InitializeComponent();
        }

        #region Events

        #region VerticalCollapse

        #region VerticalCollapsedChanged

        public void ToggleVerticalCollapse(bool isVisible)
        {
            (MainGrid.Parent as FrameworkElement).Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed;
        }

        public static readonly RoutedEvent StatusBorderClickedEvent = EventManager.RegisterRoutedEvent("StatusBorderClickedEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn));

        public event RoutedEventHandler StatusBorderClickedEventHandler
        {
            add { AddHandler(StatusBorderClickedEvent, value); }
            remove { RemoveHandler(StatusBorderClickedEvent, value); }
        }

        private void RaiseStatusBorderClickedEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(StatusBorderClickedEvent);
            RaiseEvent(newEventArgs);
        }

        private void TitleRowBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            RaiseStatusBorderClickedEvent();
        }

        private void TitleRowBorder_TouchDown(object sender, TouchEventArgs e)
        {
            RaiseStatusBorderClickedEvent();
        }

        #endregion

        #endregion

        #region MouseOver Events

        #region EnterTitleRow

        public static readonly RoutedEvent MouseEnterTitleRowEvent = EventManager.RegisterRoutedEvent("MouseEnterTitleRowEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn));

        public event RoutedEventHandler MouseEnterTitleRowEventHandler
        {
            add { AddHandler(MouseEnterTitleRowEvent, value); }
            remove { RemoveHandler(MouseEnterTitleRowEvent, value); }
        }

        private void RaiseMouseEnterTitleRowEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseEnterTitleRowEvent);
            RaiseEvent(newEventArgs);
        }

        private void TitleRowBorder_MouseEnter(object sender, MouseEventArgs e)
        {
            RaiseMouseEnterTitleRowEvent();
        }

        #endregion

        #region LeaveTitleRow

        public static readonly RoutedEvent MouseLeaveTitleRowEvent = EventManager.RegisterRoutedEvent("MouseLeaveTitleRowEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DetailsPageDataHistoryValueColumn));

        public event RoutedEventHandler MouseLeaveTitleRowEventHandler
        {
            add { AddHandler(MouseLeaveTitleRowEvent, value); }
            remove { RemoveHandler(MouseLeaveTitleRowEvent, value); }
        }

        private void RaiseMouseLeaveTitleRowEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MouseLeaveTitleRowEvent);
            RaiseEvent(newEventArgs);
        }

        private void TitleRowBorder_MouseLeave(object sender, MouseEventArgs e)
        {
            RaiseMouseLeaveTitleRowEvent();
        }

        #endregion

        #endregion

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

        #endregion

        #region Style Definitions

        private Style dataHistoryValueStyle;
        private Style dataHistoryValueAggregateStyle;
        private Style dataHistoryValueBorderStyle;

        private SolidColorBrush blueBrush;
        private SolidColorBrush greenBrush;
        private SolidColorBrush orangeBrush;
        private SolidColorBrush redBrush;
        private SolidColorBrush iconColor;

        private void SetStyles()
        {
            dataHistoryValueStyle = (Style)FindResource("DetailsPage.DataHistory.Value");
            dataHistoryValueAggregateStyle = (Style)FindResource("DetailsPage.DataHistory.Value.Aggregate");
            dataHistoryValueBorderStyle = (Style)FindResource("DetailsPage.DataHistory.ValueBorder");

            blueBrush = (SolidColorBrush)FindResource("Color.Blue");
            greenBrush = (SolidColorBrush)FindResource("Color.Green");
            orangeBrush = (SolidColorBrush)FindResource("Color.Orange");
            redBrush = (SolidColorBrush)FindResource("Color.Red");
            iconColor = (SolidColorBrush)FindResource("Color.Menu.Icon");
        }

        #endregion
    }
}
