using C4IT.F4SD.SupportCaseProtocoll.Models;
using C4IT.FASD.Base;
using C4IT.MultiLanguage;
using F4SD_AdaptableIcon;
using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Enums;
using FasdDesktopUi.Basics.Services.ProtocollService;
using FasdDesktopUi.Pages.CustomMessageBox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using static C4IT.Logging.cLogManager;
using static FasdDesktopUi.Basics.UiActions.cUiQuickTipAction;

namespace FasdDesktopUi.Basics.UserControls.QuickTip
{
    public partial class QuickTipStatusMonitor : UserControl
    {

        #region Properties

        #region QuickTipName

        public string QuickTipName
        {
            get { return (string)GetValue(QuickTipNameProperty); }
            set { SetValue(QuickTipNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for QuickTipName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty QuickTipNameProperty =
            DependencyProperty.Register("QuickTipName", typeof(string), typeof(QuickTipStatusMonitor), new PropertyMetadata("Quick Tip Name"));

        #endregion

        #region QuickTipIcon

        public IconData QuickTipIcon
        {
            get { return (IconData)GetValue(QuickTipIconProperty); }
            set { SetValue(QuickTipIconProperty, value); }
        }

        // Using a DependencyProperty as the backing store for QuickTipIcon.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty QuickTipIconProperty =
            DependencyProperty.Register("QuickTipIcon", typeof(IconData), typeof(QuickTipStatusMonitor), new PropertyMetadata(new IconData(enumInternIcons.none)));

        #endregion

        #region QuickTipElementData

        public List<cUiQuickTipElement> QuickTipElementData
        {
            get { return (List<cUiQuickTipElement>)GetValue(QuickTipElementDataProperty); }
            set { SetValue(QuickTipElementDataProperty, value); }
        }

        // Using a DependencyProperty as the backing store for QuickTipElementData.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty QuickTipElementDataProperty =
            DependencyProperty.Register("QuickTipElementData", typeof(List<cUiQuickTipElement>), typeof(QuickTipStatusMonitor), new PropertyMetadata(new List<cUiQuickTipElement>(), HandleQuickTipElementDataChanged));

        private static void HandleQuickTipElementDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is QuickTipStatusMonitor quickTip)
            {
                quickTip.QuickTipElementPanel.Children.Clear();
                quickTip._stepList.Clear();
                quickTip._indexOfStepWithFocus = -1;
                quickTip.FillElements();
            }
        }

        #endregion

        private readonly List<QuickTipStep> _stepList = new List<QuickTipStep>();

        private int _indexOfStepWithFocus = -1;

        #region StepCount

        public enum enumQuickTipCompletionStatus
        {
            incomplete,
            requiredComplete,
            complete
        }

        private enumQuickTipCompletionStatus completionStatus = enumQuickTipCompletionStatus.incomplete;

        private int stepsCompletedCount = 0;

        #endregion

        #region HasFocusIndex

        public int HasFocusIndex
        {
            get { return (int)GetValue(HasFocusIndexProperty); }
            set { SetValue(HasFocusIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HasFocusIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HasFocusIndexProperty =
            DependencyProperty.Register("HasFocusIndex", typeof(int), typeof(QuickTipStatusMonitor), new PropertyMetadata(0));

        #endregion

        #endregion

        public QuickTipStatusMonitor()
        {
            InitializeComponent();
        }

        public void FillElements()
        {
            foreach (cUiQuickTipElement element in QuickTipElementData)
            {
                switch (element.ElementType)
                {
                    case enumQuickTipElementType.Text:
                        TextBlock textBlock = new TextBlock
                        {
                            Text = element.TextBlock,
                            Margin = new Thickness(0, 0, 0, 5)
                        };
                        textBlock.SetResourceReference(TextBlock.ForegroundProperty, "FontColor.DetailsPage.DataHistory.Value");
                        QuickTipElementPanel.Children.Add(textBlock);
                        break;
                    case enumQuickTipElementType.Automated:
                    case enumQuickTipElementType.Manual:
                        QuickTipStep step = new QuickTipStep { StepData = element };
                        QuickTipElementPanel.Children.Add(step);
                        _stepList.Add(step);
                        step.RequestFocus += HandleStepRequestedFocus;
                        step.SuccessStateChanged += HandleSuccessStateChanged;
                        break;
                    default:
                        break;
                }
            }

            SetStepCount();
        }

        private void SetStepCount()
        {
            int stepCount = _stepList.Count;
            int stepsCompleted = _stepList.Count(step => step.SuccessState != enumQuickActionSuccess.unknown &&
            (!(step.SuccessState == enumQuickActionSuccess.error && step.StepData.IsRequired)));

            string stepCountText = cMultiLanguageSupport.GetItem("QuickTips.Control.StepCount");
            stepCountText = string.Format(stepCountText, stepsCompleted, stepCount);
            StepCountTextBlock.Text = stepCountText;

            stepsCompletedCount = stepsCompleted;
            CheckCompletionStatus();
        }

        private void CheckCompletionStatus()
        {

            if (stepsCompletedCount == 0)
            {
                completionStatus = enumQuickTipCompletionStatus.incomplete;
                return;
            }
            else if (stepsCompletedCount == _stepList.Count)
            {
                completionStatus = enumQuickTipCompletionStatus.complete;
                return;
            }

            foreach (QuickTipStep step in _stepList)
            {
                if (step.StepData.IsRequired && (step.SuccessState == enumQuickActionSuccess.unknown || step.SuccessState == enumQuickActionSuccess.error))
                {
                    completionStatus = enumQuickTipCompletionStatus.incomplete;
                    return;
                }
            }

            completionStatus = enumQuickTipCompletionStatus.requiredComplete;
        }

        public void UpdateAutomatedStepStatus(enumQuickActionRevisionStatus status, cFasdQuickAction quickAction)
        {
            try
            {
                var stepToUpdate = _stepList.FirstOrDefault(step => step.StepData.StepUiAction.Name == quickAction.Name);

                if (stepToUpdate is null)
                    return;

                switch (status)
                {
                    case enumQuickActionRevisionStatus.unknown:
                    case enumQuickActionRevisionStatus.inProgress:
                    case enumQuickActionRevisionStatus.canceled:
                        stepToUpdate.SuccessState = enumQuickActionSuccess.unknown;
                        break;
                    case enumQuickActionRevisionStatus.finishedSuccessfull:
                        stepToUpdate.SuccessState = enumQuickActionSuccess.finished;
                        break;
                    case enumQuickActionRevisionStatus.finishedWithError:
                        stepToUpdate.SuccessState = enumQuickActionSuccess.error;
                        break;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        private void HandleStepRequestedFocus(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!(sender is QuickTipStep step))
                    return;
                int indexOfSender = _stepList.IndexOf(step);

                if (indexOfSender == _indexOfStepWithFocus)
                    return;

                QuickTipStep currentlySelectedStep = _stepList.ElementAtOrDefault(_indexOfStepWithFocus);

                if (currentlySelectedStep != null)
                    currentlySelectedStep.HasFocus = false;

                _indexOfStepWithFocus = indexOfSender;
                step.HasFocus = true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void HandleSuccessStateChanged(object sender, RoutedEventArgs e)
        {
            try
            {
                SetStepCount();

                if (!(sender is QuickTipStep step))
                    return;

                if (step.SuccessState == enumQuickActionSuccess.unknown || step.StepData.ElementType != enumQuickTipElementType.Manual)
                    return;

                bool wasSuccessfull = step.SuccessState == enumQuickActionSuccess.finished || step.SuccessState == enumQuickActionSuccess.successfull;
                ProtocollEntryBase protocollEntry = QuickTipStepProtocollEntryOutput.GetQuickTipStepProtocollEntry(step.StepData.QuickTipElementDefinition, wasSuccessfull);

                F4SDProtocoll.Instance.Add(protocollEntry);
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
        }

        private void ButtonBorder_MouseEnter(object sender, MouseEventArgs e)
        {
            if (!(sender is Border border))
                return;

            if (!(border.Child is TextBlock textBlock))
                return;

            textBlock.SetResourceReference(Control.ForegroundProperty, "Color.FunctionMarker");
        }

        private void ButtonBorder_MouseLeave(object sender, MouseEventArgs e)
        {
            if (!(sender is Border border && border.Child is TextBlock textBlock))
                return;

            textBlock.SetResourceReference(Control.ForegroundProperty, "FontColor.DetailsPage.DataHistory.TitleColumn.OverviewTitle");
        }

        private void CompleteButton_Click(object sender, InputEventArgs e)
        {
            int finishedStepCount = _stepList.Count(step => step.SuccessState == enumQuickActionSuccess.finished);

            switch (completionStatus)
            {
                case enumQuickTipCompletionStatus.incomplete:
                    HighlightRequiredButUndoneSteps();
                    break;
                case enumQuickTipCompletionStatus.requiredComplete:
                    string completeDialogText = cMultiLanguageSupport.GetItem("QuickTips.Dialog.Complete");
                    completeDialogText = string.Format(completeDialogText, stepsCompletedCount, _stepList.Count);
                    var completeDialogResult = CustomMessageBox.Show(completeDialogText, "Quick Tip", enumHealthCardStateLevel.Warning, null, true);
                    if (completeDialogResult != true)
                        break;

                    AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, false);
                    ResetQuickTip();
                    break;
                case enumQuickTipCompletionStatus.complete:
                    AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, false);
                    ResetQuickTip();
                    break;
            }
        }

        private void HighlightRequiredButUndoneSteps()
        {
            QuickTipStep currentlySelectedStep = _stepList.ElementAtOrDefault(_indexOfStepWithFocus);

            if (currentlySelectedStep != null)
                currentlySelectedStep.HasFocus = false;
            _indexOfStepWithFocus = -1;

            foreach (QuickTipStep step in _stepList.Where(step => step.StepData.IsRequired))
            {
                if (step.SuccessState != enumQuickActionSuccess.successfull && step.SuccessState != enumQuickActionSuccess.finished)
                    step.HighlightAsRequired();
            }
        }

        private void ResetQuickTip()
        {
            Visibility = Visibility.Collapsed;
            QuickTipElementData = new List<cUiQuickTipElement>();
        }

        private void CancelButton_Click(object sender, InputEventArgs args) => CancelQuickTip();

        private void CancelQuickTip()
        {
            if (_stepList.Any(step => step.SuccessState != enumQuickActionSuccess.unknown))
                if (CustomMessageBox.Show(cMultiLanguageSupport.GetItem("QuickTips.Dialog.Cancel"), "Quick Tip", enumHealthCardStateLevel.Warning, null, true) != true)
                    return;

            Visibility = Visibility.Collapsed;

            int finishedStepCount = _stepList.Count(step => step.SuccessState == enumQuickActionSuccess.finished);
            AddQuickTipEndToProtocoll(QuickTipName, finishedStepCount, _stepList.Count, true);
            QuickTipElementData = new List<cUiQuickTipElement>();
        }

        private void AddQuickTipEndToProtocoll(string quickTipName, int finishedStepCount, int totalStepCount, bool wasCanceled)
        {
            string ascii = wasCanceled ? cMultiLanguageSupport.GetItem("QuickTips.Copy.Cancel") : cMultiLanguageSupport.GetItem("QuickTips.Copy.Finish");
            ascii = string.Format(ascii, quickTipName, finishedStepCount, totalStepCount);
            F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
        }

        private void QuickTipStatusMonitorUc_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (!IsVisible)
                return;

            string ascii = cMultiLanguageSupport.GetItem("QuickTips.Copy.Start");
            ascii = string.Format(ascii, QuickTipName);
            F4SDProtocoll.Instance.Add(new TextualProtocollEntry(ascii, ascii));
        }
    }
}
