using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using HtmlAgilityPack;
using InABox.Core;
using InABox.WPF;
using NPOI.SS.Formula.Functions;
using Syncfusion.Windows.Controls.RichTextBoxAdv;

namespace InABox.DynamicGrid
{
    public delegate void RichTextEditorChanged(object sender);
    
    public class ButtonVisibleConverter : AbstractConverter<RichTextEditorButtons, Visibility>
    {

        public Visibility Set { get; set; } = Visibility.Visible;
        public Visibility Unset { get; set; } = Visibility.Collapsed;
        
        public RichTextEditorButtons Flag { get; set; } = RichTextEditorButtons.None;
        
        public override Visibility Convert(RichTextEditorButtons value)
        {
            return value != RichTextEditorButtons.None && value.HasFlag(Flag) ? Set : Unset;
        }
    }
    
    /// <summary>
    ///     Interaction logic for RichTextEditorControl.xaml
    /// </summary>
    public partial class RichTextEditor : UserControl
    {
        // public static readonly DependencyProperty HideToolbarProperty =
        //     DependencyProperty.Register(nameof(HideToolbar), typeof(bool), typeof(RichTextEditor));

        public static readonly DependencyProperty ZoomFactorProperty =
            DependencyProperty.Register(nameof(ZoomFactor), typeof(double), typeof(RichTextEditor));

        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register(
                "Color",
                typeof(Color),
                typeof(RichTextEditor),
                new PropertyMetadata(default(Color), OnBackgroundPropertyChanged));

        private bool bdirty;
        private bool bReady;
        private string curvalue = "";

        public RichTextEditorButtons VisibleButtons
        {
            get => ViewModel.VisibleButtons;
            set => ViewModel.VisibleButtons = value;
        }


        public RichTextEditor()
        {
            InitializeComponent();

            Bold.SmallIcon = Wpf.Resources.Bold16.AsBitmapImage(16, 16);
            Italic.SmallIcon = Wpf.Resources.Italic16.AsBitmapImage(16, 16);
            Underline.SmallIcon = Wpf.Resources.Underline16.AsBitmapImage(16, 16);
            AlignLeft.SmallIcon = Wpf.Resources.AlignTextLeft16.AsBitmapImage(16, 16);
            AlignCentre.SmallIcon = Wpf.Resources.AlignTextCenter16.AsBitmapImage(16, 16);
            AlignRight.SmallIcon = Wpf.Resources.AlignTextRight16.AsBitmapImage(16, 16);
            AlignJustify.SmallIcon = Wpf.Resources.AlignTextJustify16.AsBitmapImage(16, 16);
            Hyperlink.SmallIcon = Wpf.Resources.Hyperlink16.AsBitmapImage(16, 16);
            Picture.SmallIcon = Wpf.Resources.Picture16.AsBitmapImage(16, 16);
            Table.SmallIcon = Wpf.Resources.Table16.AsBitmapImage(16, 16);
            ZoomIn.SmallIcon = Wpf.Resources.zoomin.AsBitmapImage(16, 16);
            ZoomOut.SmallIcon = Wpf.Resources.zoomout.AsBitmapImage(16, 16);
            Editor.CaretBrush = new SolidColorBrush(Colors.Black);
            Editor.FontFamily = new FontFamily("Calibri");
            Editor.FontSize = 10.0F;
            Editor.Foreground = new SolidColorBrush(Colors.Black);
            ZoomFactor = 150;
            
            Text = "";
        }
        
        // public bool HideToolbar
        // {
        //     get => (bool)GetValue(HideToolbarProperty);
        //     set
        //     {
        //         SetValue(HideToolbarProperty, value);
        //         Toolbar.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
        //     }
        // }

        public double ZoomFactor
        {
            get => (double)GetValue(ZoomFactorProperty);
            set
            {
                SetValue(ZoomFactorProperty, value);
                Editor.ZoomFactor = value;
            }
        }

        public string Text
        {
            get => Save();
            set => Load(value);
        }

        public RichTextEditorChanged? OnChanged { get; set; }

        public Color Color
        {
            get => (Color)GetValue(ColorProperty);
            set
            {
                SetValue(ColorProperty, value);
                Editor.Background = new SolidColorBrush(value);
            }
        }

        public void Load(string content)
        {
            if (content == null)
                content = "";
            content = HTMLUtils.TextToHtml(content); 
            using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(content)))
            {
                Editor.Load(ms, FormatType.Html);
            }
            
            VerticalAlignment = VerticalAlignment.Top;
            VerticalAlignment = VerticalAlignment.Stretch;

            curvalue = content;
            bdirty = false;
        }

        public string Save()
        {
            if (bdirty)
            {
                using (var ms = new MemoryStream())
                {
                    Editor.Save(ms, FormatType.Html);
                    curvalue = Encoding.UTF8.GetString(ms.GetBuffer());
                    curvalue = HTMLUtils.HtmlToText(curvalue);
                }

                bdirty = false;
            }

            return curvalue;
        }
        
        private void RichTextBoxAdv_ContentChanged(object obj, ContentChangedEventArgs args)
        {
            bdirty = true;
        }

        public void SetColor(Color color)
        {
            Editor.Background = new SolidColorBrush(color);
        }

        private static void OnBackgroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not RichTextEditor source) return;
            source.SetColor((Color)e.NewValue);
        }


        private void RichTextBoxAdv_LostFocus(object sender, RoutedEventArgs e)
        {
            if (bReady)
                OnChanged?.Invoke(this);
            bReady = true;
        }

        private void ZoomIn_Click(object sender, RoutedEventArgs e)
        {
            Editor.ZoomFactor = Editor.ZoomFactor * 1.5F;
        }

        private void ZoomOut_Click(object sender, RoutedEventArgs e)
        {
            Editor.ZoomFactor = Editor.ZoomFactor / 1.5F;
        }

        private void Editor_RequestNavigate(object obj, RequestNavigateEventArgs args)
        {
            var processStartInfo = new ProcessStartInfo(args.Hyperlink.NavigationLink);
            processStartInfo.UseShellExecute = true;
            Process.Start(processStartInfo);
        }

        /// <summary>
        /// Handles the ImageNodeVisited event of the richTextBoxAdv control.
        /// We are setting the image "source" property to empty to save the image inline
        /// See: https://help.syncfusion.com/uwp/richtextbox/faq-section/how-to-export-the-inserted-image-as-an-embedded-image-in-html-in-sfrichtextboxadv
        /// </summary>
        /// <param name="obj">The source of the event.</param>
        /// <param name="args">The <see cref="ImageNodeVisitedEventArgs"/> instance containing the event data.</param>
        private void HtmlImportExportSettings_OnImageNodeVisited(object obj, ImageNodeVisitedEventArgs args)
        {
            if (args.IsSaving)
                args.Source = string.Empty;
        }
        
    }
}