using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using InABox.Core;
using InABox.WPF;
using Microsoft.Xaml.Behaviors;
using Syncfusion.UI.Xaml.Grid;
using Syncfusion.UI.Xaml.TreeGrid;

namespace InABox.DynamicGrid;

public class DynamicGridMaskColumnButtonClickArgs
{
    public object? Value { get; set; }
    public DynamicGridMaskColumnButtonClickArgs(object? value)
    {
        Value = value;
    }
}

public enum DynamicGridMaskColumnButtonPosition
{
    Left,
    Right
}

public class DynamicGridMaskColumnButton
{
    public BitmapImage? Image { get; set; }
    
    public Visibility Visibility { get; set; }

    public DynamicGridMaskColumnButtonPosition Position { get; set; } = DynamicGridMaskColumnButtonPosition.Right;
    
    public Action<DynamicGridMaskColumnButton,DynamicGridMaskColumnButtonClickArgs>? Clicked { get; set; }

    public object? DoClick(object? value)
    {
        var args = new DynamicGridMaskColumnButtonClickArgs(value);
        Clicked?.Invoke(this, args);
        return args.Value;
    }
}

public abstract class DynamicGridMaskColumn<TEditor> : DynamicGridEditorColumn< TEditor, GridTemplateColumn, TreeGridTemplateColumn>
    where TEditor : class,new() 
{

    protected abstract Behavior? CreateBehaviour();

    protected abstract IValueConverter? CreateConverter();

    protected virtual Tuple<DataTemplate, DataTemplate> CreateTemplates(GridColumnBase column, TEditor editor, string mapping)
    {
        var converter = CreateConverter();
        var cellTemplate = TemplateGenerator.CreateDataTemplate
        (
            () =>
            {
                var result = new Label
                {
                    HorizontalContentAlignment = column.TextAlignment == TextAlignment.Left
                        ? HorizontalAlignment.Left
                        : column.TextAlignment == TextAlignment.Center
                            ? HorizontalAlignment.Center
                            : HorizontalAlignment.Right,
                    VerticalContentAlignment = VerticalAlignment.Center
                };
                var binding = new Binding()
                {
                    Path = new PropertyPath(mapping),
                    Converter = converter
                };
                result.SetBinding(Label.ContentProperty, binding);
                return result;
            }
        );
        var editTemplate = TemplateGenerator.CreateDataTemplate
        (
            () =>
            {
                var border = new Border()
                {
                    BorderBrush = new SolidColorBrush(Colors.Gray),
                    BorderThickness = new Thickness(0.75),
                    Padding = new Thickness(0),
                    Margin = new Thickness(0)
                };
                    
                var dock = new DockPanel();
                dock.SourceUpdated += OnSourceUpdated;
                dock.TargetUpdated += OnTargetUpdated;
                border.Child = dock;
                
                var textbox = new TextBox
                {
                    CharacterCasing = CharacterCasing.Upper,
                    TextAlignment = column.TextAlignment,
                    BorderThickness = new Thickness(0),
                    //Padding = new Thickness(2, 0, 0, 0),
                    VerticalContentAlignment = VerticalAlignment.Center,
                    Background = new SolidColorBrush(Colors.White)
                };
                
                textbox.SetBinding(TextBox.TextProperty, new Binding()
                {
                    Path = new PropertyPath(mapping),
                    Converter = converter,
                    NotifyOnSourceUpdated = true,
                    NotifyOnTargetUpdated = true,

                });
                
                var behaviour = CreateBehaviour();
                if (behaviour != null)
                    Interaction.GetBehaviors(textbox).Add(behaviour);
                
                textbox.SetValue(FocusManagerHelper.FocusedElementProperty, true);
                textbox.SetValue(DockPanel.DockProperty,Dock.Left);
                
                var defs = CreateButtons();
                if (defs?.Any() == true)
                {
                    foreach (var def in defs)
                    {
                        Button button = new Button()
                        {
                            Tag = def,
                            Content = new Image() { Source = def.Image },
                            Padding = new Thickness(2),
                            Width = 25,
                            BorderThickness = new Thickness(0),
                            Background = new SolidColorBrush(Colors.White),
                            Visibility = def.Visibility,
                        };
                        button.Click += (sender, args) =>
                        {
                            var cvt = CreateConverter();
                            var val = cvt != null
                                ? cvt.ConvertBack(textbox.Text, typeof(object), null, CultureInfo.CurrentCulture)
                                : textbox.Text;
                            val = def.DoClick(val);
                            textbox.Text = cvt != null
                                ? cvt.Convert(val, typeof(String), null, CultureInfo.CurrentCulture) as String ?? ""
                                : val?.ToString() ?? "";
                            textbox.GetBindingExpression(TextBox.TextProperty)?.UpdateSource();
                            button.Content = new Image() { Source = def.Image };
                            button.Visibility = def.Visibility;
                        };
                        button.SetValue(DockPanel.DockProperty,def.Position == DynamicGridMaskColumnButtonPosition.Left ? Dock.Left : Dock.Right);
                        dock.Children.Add(button);
                    }
                }
                
                dock.Children.Add(textbox);
                
                return border;
            }
            
        );
        return new(cellTemplate, editTemplate);
    }
    
    protected override void Configure(GridTemplateColumn column, TEditor editor)
    {
        var (cellTemplate, editTemplate) = CreateTemplates(column, editor, MappingName);
        column.CellTemplate = cellTemplate;
        column.EditTemplate = editTemplate;
        
        column.SetCellBoundValue = false;
    }
    protected override void Configure(TreeGridTemplateColumn column, TEditor editor)
    {
        var (cellTemplate, editTemplate) = CreateTemplates(column, editor, TreeMappingName);
        column.CellTemplate = cellTemplate;
        column.EditTemplate = editTemplate;
        
        column.SetCellBoundValue = false;
    }

    protected virtual DynamicGridMaskColumnButton[]? CreateButtons()
    {
        return null;
    }
    
    private void OnTargetUpdated(object? sender, DataTransferEventArgs e)
    {
        if (sender is DockPanel dock && e.Source is TextBox textbox && e.Property == TextBox.TextProperty)
        {
            var buttons = dock?.Children.OfType<Button>().ToArray();
            var defs = buttons?.Select(x => x.Tag).OfType<DynamicGridMaskColumnButton>()?.ToArray();
            if (defs?.Any() == true)
            {
                var cvt = CreateConverter();
                var val = cvt != null
                    ? cvt.ConvertBack(textbox.Text, typeof(object), null, CultureInfo.CurrentCulture)
                    : textbox.Text;
                UpdateButtons(val, defs);
                if (buttons != null)
                    foreach (var button in buttons)
                    {
                        var def = button.Tag as DynamicGridMaskColumnButton;
                        button.Content = new Image() { Source = def?.Image };
                        button.Visibility = def?.Visibility ?? Visibility.Collapsed;
                    }
            }
        }
    }
    
    protected virtual void UpdateButtons(object? value, DynamicGridMaskColumnButton[]? buttons)
    {
        
    }

    private void OnSourceUpdated(object? sender, DataTransferEventArgs e)
    {
        if (sender is DockPanel dock && e.Source is TextBox textbox && e.Property == TextBox.TextProperty)
        {
            var buttons = dock?.Children.OfType<Button>().ToArray();
            SourceUpdated(textbox.Text, buttons ?? new Button[] { });
        }
    }

    protected virtual void SourceUpdated(string text, Button[] buttons)
    {
        
    }

    protected DynamicGridMaskColumn(DynamicGridColumn definition) : base(definition)
    {
    }
}