using F4SD_AdaptableIcon.Enums;
using FasdDesktopUi.Basics.Helper;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Threading;
using static C4IT.Logging.cLogManager;


namespace FasdDesktopUi.Basics.UserControls
{
    public partial class Notepad : UserControl
    {
        #region Variables

        private bool IsBold = false;
        private bool IsItalic = false;
        private bool IsUnderline = false;
        private bool IsDecimal = false;
        private bool IsBullet = false;
        private bool CanUndo = false;
        private bool CanRedo = false;

        #endregion

        #region Properties and Fields

        private static DispatcherTimer saveTimer;

        public EventHandler<bool> LockStatusChanged { get; set; }

        public EventHandler<bool> NotepadVisibilityChanged { get; set; }

        public EventHandler<bool> IsUndockedChanged { get; set; }

        #region DataProvider

        private cSupportCaseDataProvider DataProvider;

        /*
        {
            get { return (cDataProviderBase)GetValue(DataProviderProperty); }
            set {
                SetValue(DataProviderProperty, value);
            }
        }
        */

        /*
        private static readonly DependencyProperty DataProviderProperty =
            DependencyProperty.Register("DataProvider", typeof(cDataProviderBase), typeof(Notepad), new PropertyMetadata(null));
        */

        #endregion

        #region IsUndocked

        public bool IsUndocked
        {
            get { return (bool)GetValue(IsUndockedProperty); }
            set { SetValue(IsUndockedProperty, value); }
        }

        public static readonly DependencyProperty IsUndockedProperty =
            DependencyProperty.Register("IsUndocked", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleUndockedChanged)));

        private static void HandleUndockedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (!(d is Notepad _me))
                    return;

                _me.ToggleIconVisibility();

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

        #endregion

        #region IsLocked

        public bool IsLocked
        {
            get { return (bool)GetValue(IsLockedProperty); }
            set { SetValue(IsLockedProperty, value); }
        }

        public static readonly DependencyProperty IsLockedProperty =
            DependencyProperty.Register("IsLocked", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleLockedChanged)));

        private static void HandleLockedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            try
            {
                if (!(d is Notepad _me))
                {
                    return;
                }

                _me.LockNotepadIcon.SelectedInternIcon = _me.IsLocked ? F4SD_AdaptableIcon.Enums.enumInternIcons.lock_closed : F4SD_AdaptableIcon.Enums.enumInternIcons.lock_open;
                
                _me.CloseNotepadIcon.IsEnabled = _me.IsLocked ? false : true;

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

        }

        #endregion

        #region IsTicketDialog

        //public bool IsTicketDialog { get; set; }



        public bool IsTicketDialog
        {
            get { return (bool)GetValue(IsTicketDialogProperty); }
            set { SetValue(IsTicketDialogProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsTicketDialog.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsTicketDialogProperty =
            DependencyProperty.Register("IsTicketDialog", typeof(bool), typeof(Notepad), new PropertyMetadata(new PropertyChangedCallback(HandleTicketDialogChanged)));

        private static void HandleTicketDialogChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            try
            {

                if (!(d is Notepad _me))
                {
                    return;
                }
                
            }
            catch(Exception E)
            {
                LogException(E);
            }
        }

        #endregion

        #endregion

        #region Constructor

        public Notepad(cSupportCaseDataProvider dataProvider)
        {
            DataProvider = dataProvider;
            InitializeComponent();
            saveTimer = new DispatcherTimer(TimeSpan.FromSeconds(0.75), DispatcherPriority.Render, SaveNotes, Dispatcher.CurrentDispatcher);
            IsLocked = cFasdCockpitConfig.Instance.IsNotepadVisibleDocked;
        }

        #endregion

        #region Methods
        
        
        private void NotepadRichTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            try
            {
                if (DataProvider is null)
                    return;

                if (DataProvider?.CaseNotes?.Parent is RichTextBox parentBox)
                    parentBox.Document = new FlowDocument();

                if (!(sender is RichTextBox senderElement))
                    return;

                senderElement.Document = DataProvider.CaseNotes;
                senderElement.CaretPosition = senderElement.CaretPosition.DocumentEnd;
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private async void NotepadRichTextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                if (!(e.NewValue is bool isVisible && isVisible))
                    return;

                await Task.Delay(50);
                NotepadRichTextBox.Focus();
                Keyboard.Focus(NotepadRichTextBox);

                NotepadRichTextBox_GotKeyboardFocus(sender, null);
            }
            catch (Exception E)
            {
                LogException(E);
            }


        }

        #region CopyIcon Click

        private async void CopyIcon_Click(object sender)
        {
            try
            {
                DataObject copyObject = new DataObject();

                StringBuilder stringBuilderUnicode = new StringBuilder();
                cRichTextBoxHelper.TraverseBlockAsUnicode(NotepadRichTextBox.Document.Blocks, stringBuilderUnicode);
                copyObject.SetData(DataFormats.UnicodeText, stringBuilderUnicode.ToString());

                StringBuilder stringBuilderHtml = new StringBuilder();
                cRichTextBoxHelper.TraverseBlockAsHtml(NotepadRichTextBox.Document.Blocks, stringBuilderHtml);
                var copyText = cUtility.GetHtmlFrame(stringBuilderHtml.ToString());
                copyObject.SetData(DataFormats.Html, copyText);

                TextRange tr = new TextRange(NotepadRichTextBox.Document.ContentStart, NotepadRichTextBox.Document.ContentEnd);
                using (MemoryStream ms = new MemoryStream())
                {
                    tr.Save(ms, DataFormats.Rtf);
                    string rtfText = ASCIIEncoding.Default.GetString(ms.ToArray());
                    copyObject.SetData(DataFormats.Rtf, rtfText);
                }

                Clipboard.SetDataObject(copyObject);

                await cUtility.ChangeIconToCheckAsync(CopyIcon);
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void CopyIcon_TouchDown(object sender, TouchEventArgs e)
        {
            CopyIcon_Click(sender);
        }

        private void CopyIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            CopyIcon_Click(sender);
        }

        #endregion

        #region Popout

        private void ToggleDockButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {

            try
            {
                IsUndocked = !IsUndocked;
                IsUndockedChanged?.Invoke(this, IsUndocked);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        private void ToggleDockButton_TouchDown(object sender, TouchEventArgs e)
        {

            try
            {
                IsUndocked = !IsUndocked;
                IsUndockedChanged?.Invoke(this, IsUndocked);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        #endregion

        #region Save Notes

        private void SaveNotes(object sender, EventArgs e)
        {
            try
            {
                saveTimer?.Stop();

                if (DataProvider is null)
                    return;

                Dispatcher.Invoke(() => DataProvider.SaveCaseNotes());
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void NotepadRichTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
                
            saveTimer?.Stop();
            saveTimer?.Start();

            CheckUndo_TextChanged(sender, e);
        }

        #endregion

        #region RichTextBox SelectionChanged

        private void NotepadRichTextBox_SelectionChanged(object sender, RoutedEventArgs e)
        {

            try
            {
                var selection = NotepadRichTextBox.Selection;

                if (selection != null)
                {

                    if ((FontWeight)selection.GetPropertyValue(TextElement.FontWeightProperty) == FontWeights.Bold)
                    {
                        if (IsBold == false)
                        {
                            SelectedTextIsBold(true);
                            IsBold = true;
                        }
                    }
                    else
                    {
                        if (IsBold == true)
                        {
                            SelectedTextIsBold(false);
                            IsBold = false;
                        }
                    }

                    if ((FontStyle)selection.GetPropertyValue(TextElement.FontStyleProperty) == FontStyles.Italic)
                    {
                        if (IsItalic == false)
                        {
                            SelectedTextIsItalic(true);
                            IsItalic = true;
                        }
                    }
                    else
                    {
                        if (IsItalic == true)
                        {
                            SelectedTextIsItalic(false);
                            IsItalic = false;
                        }
                    }

                    if ((TextDecorationCollection)selection.GetPropertyValue(Inline.TextDecorationsProperty) == TextDecorations.Underline)
                    {
                        if (IsUnderline == false)
                        {
                            SelectedTextIsUnderlined(true);
                            IsUnderline = true;
                        }
                    }
                    else
                    {
                        if (IsUnderline == true)
                        {
                            SelectedTextIsUnderlined(false);
                            IsUnderline = false;
                        }
                    }

                    if (selection.Start != null && selection.Start.Paragraph != null)
                    {

                        if (selection.Start.Paragraph.Parent is ListItem listItem)
                        {
                            if (listItem.List != null && listItem.List.MarkerStyle == TextMarkerStyle.Decimal)
                            {
                                if (IsDecimal == false)
                                {
                                    SelectedTextIsDecimal(true);
                                    IsDecimal = true;
                                }
                            }
                            else
                            {
                                if (IsDecimal == true)
                                {
                                    SelectedTextIsDecimal(false);
                                    IsDecimal = false;
                                }
                            }
                        }
                        else
                        {
                            if (IsDecimal == true)
                            {
                                SelectedTextIsDecimal(false);
                                IsDecimal = false;
                            }
                        }

                    }

                    if (selection.Start != null && selection.Start.Paragraph != null)
                    {

                        if (selection.Start.Paragraph.Parent is ListItem listItem)
                        {
                            if (listItem.List != null && listItem.List.MarkerStyle == TextMarkerStyle.Disc)
                            {
                                if (IsBullet == false)
                                {
                                    SelectedTextIsDisc(true);
                                    IsBullet = true;
                                }
                            }
                            else
                            {
                                if (IsBullet == true)
                                {
                                    SelectedTextIsDisc(false);
                                    IsBullet = false;
                                }
                            }
                        }
                        else
                        {
                            if (IsBullet == true)
                            {
                                SelectedTextIsDisc(false);
                                IsBullet = false;
                            }
                        }

                    }

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

        }

        private void SelectedTextIsBold(bool isActive)
        {

            try
            {
                if (isActive != true)
                {
                    BoldIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                    return;
                }

                BoldIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");

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


        }

        private void SelectedTextIsItalic(bool isActive)
        {

            try
            {
                if (isActive != true)
                {
                    ItalicIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                    return;
                }

                ItalicIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");

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

        }

        private void SelectedTextIsUnderlined(bool isActive)
        {

            try
            {
                if (isActive != true)
                {
                    UnderlineIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                    return;
                }

                UnderlineIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");

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

        }

        private void SelectedTextIsDecimal(bool isActive)
        {

            try
            {
                if (isActive != true)
                {
                    NumberingIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                    return;
                }

                NumberingIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");

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

        }

        private void SelectedTextIsDisc(bool isActive)
        {

            try
            {
                if (isActive != true)
                {
                    BulletsIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                    return;
                }

                BulletsIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Pinned");

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

        }

        private void TextBoxIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            NotepadRichTextBox_SelectionChanged(sender, e);
        }

        #endregion

        #region Undo/Redo

        private void CheckUndo_TextChanged(object sender, TextChangedEventArgs e)
        {

            if (NotepadRichTextBox.CanUndo == true && CanUndo == false)
            {
                UndoIcon.IsEnabled = true;
                UndoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                CanUndo = true;
            }
            else if (NotepadRichTextBox.CanUndo == false && CanUndo == true)
            {
                UndoIcon.IsEnabled = false;
                UndoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Disabled");
                CanUndo = false;
            }

            if (NotepadRichTextBox.CanRedo == true && CanRedo == false)
            {
                RedoIcon.IsEnabled = true;
                RedoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon");
                CanRedo = true;
            }
            else if (NotepadRichTextBox.CanRedo == false && CanRedo == true)
            {
                RedoIcon.IsEnabled = false;
                RedoIcon.Style = (Style)FindResource("Menu.MenuBar.PinnedIcon.Disabled");
                CanRedo = false;
            }

        }


        #endregion

        #region Control Icons

        #region Visibility

        private void ToggleIconVisibility()
        {

            try
            {
                ToggleDockButton.Visibility = IsUndocked ? Visibility.Collapsed : Visibility.Visible;
                LockNotepadIcon.Visibility = IsUndocked ? Visibility.Collapsed : Visibility.Visible;
                CloseNotepadIcon.IsEnabled = IsUndocked ? true : !IsLocked;

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

        }

        #endregion


        private void NotepadIcon_Click(object sender, InputEventArgs e)
        {
            try
            {
                if (!(sender is FrameworkElement senderElement))
                    return;

                switch (senderElement.Tag)
                {
                    case "lock":
                        LockNotepad();
                        break;
                    case "close":
                        CloseNotepad();
                        break;
                    default:
                        break;
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void CloseNotepadIcon_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
                CloseNotepad();
        }

        private void CloseNotepadIcon_TouchDown(object sender, TouchEventArgs e)
        {
            CloseNotepad();
        }

        private void LockNotepad()
        {

            try
            {

                if (IsLocked)
                {
                    LockNotepadIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.SoftContrast");
                    LockNotepadIcon.SelectedInternIcon = enumInternIcons.lock_open;
                }
                else
                {
                    LockNotepadIcon.SetResourceReference(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty, "Color.Menu.Icon");
                    LockNotepadIcon.SelectedInternIcon = enumInternIcons.lock_closed;
                }

                LockNotepadIcon.BorderPadding = new Thickness(5.5);

                IsLocked = !IsLocked;
                LockStatusChanged?.Invoke(this, IsLocked);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        private void LockNotepadIcon_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
                LockNotepad();
        }

        private void LockNotepadIcon_TouchDown(object sender, TouchEventArgs e)
        {
            LockNotepad();
        }

        private void LockNotepadIcon_MouseLeave(object sender, MouseEventArgs e)
        {
            (sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.PrimaryIconColorProperty);
            (sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.SelectedInternIconProperty);
            (sender as AdaptableIcon.AdaptableIcon).ClearValue(AdaptableIcon.AdaptableIcon.BorderPaddingProperty);
        }

        private void CloseNotepad()
        {

            try
            {
                if (IsUndocked == true)
                {
                    IsUndocked = !IsUndocked;
                    IsUndockedChanged?.Invoke(this, IsUndocked);
                    return;
                }
                NotepadVisibilityChanged?.Invoke(this, true);
               
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        #endregion

        #endregion

    }
}
