using InABox.Core;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using InABox.WPF;

namespace InABox.DynamicGrid
{
    public class DFMultiSignatureControl : DynamicFormFieldControl<DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties, Dictionary<string, byte[]>, Dictionary<string, byte[]>?>
    {
        private Grid Grid = null!; // Late-initialised
        private Grid Images = null!; // Late-initialised
        private bool Enabled = true;

        static DFMultiSignatureControl()
        {
            IsEnabledProperty.OverrideMetadata(
                typeof(DFMultiSignatureControl),
                new UIPropertyMetadata(
                    true,
                    ControlIsEnabledChanged));
        }

        private static void ControlIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            var control = (DFMultiSignatureControl)obj;
            control.IsEnabled = true;
            control.Enabled = (bool)e.NewValue;
        }

        protected override FrameworkElement Create()
        {
            Grid = new Grid();
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

            Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            Grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

            var imagesScroll = new ScrollViewer
            {
                HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
                VerticalScrollBarVisibility = ScrollBarVisibility.Disabled,
                Background = new SolidColorBrush(Colors.Gray)
            };

            Images = new Grid { Height = 150 };

            Images.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            Images.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });

            imagesScroll.Content = Images;

            var clearButton = new Button
            {
                Content = "Clear",
                Margin = new Thickness(0, 5, 0, 0),
                Width = 60,
                Height = 35
            };
            clearButton.Click += MultiSignatureClear_Click;

            var addButton = new Button
            {
                Content = "Add",
                Margin = new Thickness(0, 5, 0, 0),
                Width = 60,
                Height = 35
            };
            addButton.Click += MultiSignatureAdd_Click;

            imagesScroll.SetGridPosition(0, 0, 1, 3);
            clearButton.SetGridPosition(1, 0, 1, 1);
            addButton.SetGridPosition(1, 2, 1, 1);
            Grid.Children.Add(imagesScroll);
            Grid.Children.Add(clearButton);
            Grid.Children.Add(addButton);

            return Grid;
        }
        private void AddMultiSignature(BitmapSource? source, string name)
        {
            var image = new Image();
            if (source != null)
            {
                image.Source = source;

                var label = new Label
                {
                    Content = name.ToUpper(),
                    VerticalContentAlignment = VerticalAlignment.Center,
                    VerticalAlignment = VerticalAlignment.Stretch,
                    HorizontalContentAlignment = HorizontalAlignment.Center
                };

                var column = Images.ColumnDefinitions.Count;

                var menu = new ContextMenu();
                menu.AddItem("Remove Signature", null, image, MultiSignatureRemove_Click);
                image.ContextMenuOpening += (sender, args) =>
                {
                    if (!Enabled) args.Handled = true;
                };

                Images.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

                image.ContextMenu = menu;
                label.ContextMenu = menu;

                image.SetGridPosition(0, column, 1, 1);
                label.SetGridPosition(1, column, 1, 1);

                Images.Children.Add(image);
                Images.Children.Add(label);
            }
        }

        private void MultiSignatureAdd_Click(object sender, RoutedEventArgs e)
        {
            var window = new SignaturePadWindow(null, true);

            if (window.ShowDialog() == true)
            {
                var sigName = window.SignatureName.ToUpper().Trim();
                if (string.IsNullOrWhiteSpace(sigName))
                {
                    MessageBox.Show("Name cannot be empty!");
                }
                else if (Images.Children.Cast<UIElement>().Any(x => x is Label lbl && (string)lbl.Content == sigName))
                {
                    MessageBox.Show("A signature with that name already exists!");
                }
                else
                {
                    AddMultiSignature(window.Image, window.SignatureName);
                    ChangeField();
                }
            }
        }
        private void MultiSignatureRemove_Click(Image image)
        {
            var imageColumn = Grid.GetColumn(image);

            var removes = new List<UIElement>();
            foreach (var child in Images.Children)
            {
                if (child is UIElement el)
                {
                    var column = Grid.GetColumn(el);
                    if (column == imageColumn)
                        removes.Add(el);
                    else if (column > imageColumn)
                        Grid.SetColumn(el, column - 1);
                }
            }

            foreach (var element in removes)
            {
                Images.Children.Remove(element);
            }
            ChangeField();
        }

        private void MultiSignatureClear_Click(object sender, RoutedEventArgs e)
        {
            if (Images.Children.Count > 0)
            {
                Images.Children.Clear();
                ChangeField();
            }
        }

        public override Dictionary<string, byte[]>? GetSerializedValue()
        {
            return GetValue();
        }

        public override void SetSerializedValue(Dictionary<string, byte[]>? value)
        {
            SetValue(value);
        }

        public override Dictionary<string, byte[]> GetValue()
        {
            var columns = Images.Children.Cast<UIElement>().GroupBy(x => Grid.GetColumn(x));
            var data = new Dictionary<string, byte[]>();
            foreach (var column in columns)
            {
                if (column.FirstOrDefault(x => x is Image) is Image image
                    && column.FirstOrDefault(x => x is Label) is Label label)
                {
                    var imgData = EmbeddedImageUtilities.SaveImageToBytes(image, false, new PngBitmapEncoder());
                    if (imgData != null && label.Content is string str)
                    {
                        data.Add(str, imgData);
                    }
                }
            }
            return data;
        }

        public override void SetValue(Dictionary<string, byte[]>? value)
        {
            Images.Children.Clear();

            if (value is IDictionary<string, byte[]> data)
            {
                foreach (var (name, imgData) in data)
                {
                    AddMultiSignature(ImageUtils.BitmapImageFromBytes(imgData), name);
                }
            }
        }

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == IsEnabledProperty)
            {
                Grid.RowDefinitions[1].Height = (bool)e.NewValue
                    ? GridLength.Auto
                    : new GridLength(0);
            }
        }
        protected override bool IsEmpty() => Images.Children.Count == 0;
    }
}
