using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using InABox.Core;
using InABox.WPF;
using NPOI.SS.Formula.Functions;
using Syncfusion.UI.Xaml.Grid;
using Syncfusion.UI.Xaml.TreeGrid;
using Columns = InABox.Core.Columns;

namespace InABox.DynamicGrid;

public class PopupConverter : IMultiValueConverter
{

    private Dictionary<string, object?> _dictionary = new Dictionary<string, object?>();

    private Type _type;
            
    public PopupConverter(IColumns columns, Type type)
    {
        foreach (var column in columns.ColumnNames())
            _dictionary[column] = null;
        _type = type;
    }
            
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if ((values.Length != _dictionary.Keys.Count))
            return "";
        for (int i = 0; i < values.Length; i++)
            _dictionary[_dictionary.Keys.ElementAt(i)] = values[i] == DependencyProperty.UnsetValue ? null : values[i];
        return LookupFactory.FormatLookup(_type, _dictionary, Array.Empty<string>());
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class DynamicGridPopupColumn<TEntity> : DynamicGridEditorColumn< PopupEditor, GridTemplateColumn, TreeGridTemplateColumn>, IDynamicGridEditorColumn<TEntity>
    where TEntity : BaseObject, new()
{
    public Func<BaseObject?>? GetEntity { get; set; }

    private IColumns GetLinkColumns(Type type, String prefix)
    {
        var prefixwithstop = $"{prefix.ToUpper()}.";
        var cols = Columns.None(type);
        var props = DatabaseSchema.Properties(typeof(TEntity))
            .Where(x => x.Name.ToUpper().StartsWith(prefixwithstop));
        foreach (var prop in props)
            cols.Add(prop.Name.Remove(0,prefixwithstop.Length));
        return cols;

    }
    
    private void PopupList(Type type, string prefix, IColumns columns)
    {
        var entity = GetEntity?.Invoke() as TEntity;
        if (entity != null)
        {
            var msdtype = typeof(MultiSelectDialog<>).MakeGenericType(type);
            var msd = Activator.CreateInstance(
                msdtype,
                new object?[]
                {
                    LookupFactory.DefineLookupFilter(typeof(TEntity), type, prefix, new TEntity[] { entity }),
                    columns,
                    false
                }
            ) as IMultiSelectDialog;
            if (msd.ShowDialog())
            {
                var row = msd.Data().Rows.FirstOrDefault();
                if (row != null)
                    UpdateColumnValue(row,prefix);
            }
        }
    }
    
    private void UpdateColumnValue(CoreRow row, string prefix)
    {
        var dict = row.ToDictionary();
        var updates = dict.ToDictionary(x => $"{prefix}.{x.Key}", x => x.Value);
        this.UpdateData(updates);
    }

    private Tuple<DataTemplate, DataTemplate> GetTemplates(GridColumnBase column, PopupEditor editor)
    {
        var prefix = String.Join(".", Definition.ColumnName.Split('.').Reverse().Skip(1).Reverse());
        var displaycols = new List<String>();
        var lookupcolumns = LookupFactory.DefineLookupColumns(typeof(TEntity), editor.Type, prefix);
        foreach (var lookupcolumn in lookupcolumns)
        {
            var displaycol = String.IsNullOrWhiteSpace(prefix)
                ? lookupcolumn.Property
                : $"{prefix}.{lookupcolumn.Property}";            
            ExtraColumns.Add(displaycol);
            displaycols.Add(displaycol.Replace('.', '_'));
        }
        
        var cell = TemplateGenerator.CreateDataTemplate
        (
            () =>
            {
                var result = new Label();
                var binding = new MultiBinding();
                foreach (var displaycol in displaycols)
                    binding.Bindings.Add(new Binding(displaycol));
                binding.Converter = new PopupConverter(lookupcolumns, editor.Type);
                result.SetBinding(Label.ContentProperty, binding);
                return result;
            }
        );
        var edit = TemplateGenerator.CreateDataTemplate
        (
            () =>
            {
                var result = new DockPanel();

                var button = new Button();
                button.Content = "..";
                button.Width = 25;
                button.SetValue(DockPanel.DockProperty, Dock.Right);
                button.Tag = column;
                button.BorderThickness = new Thickness(0.75, 0, 0, 0);
                button.Margin = new Thickness(0);

                button.Click += (sender, args) =>
                {
                    PopupList(editor.Type, prefix, GetLinkColumns(editor.Type,prefix));
                };
                result.Children.Add(button);

                var label = new Label();
                var binding = new MultiBinding();
                foreach (var displaycol in displaycols)
                    binding.Bindings.Add(new Binding(displaycol));
                binding.Converter = new PopupConverter(lookupcolumns, editor.Type);
                label.SetBinding(Label.ContentProperty, binding);
                label.SetValue(DockPanel.DockProperty, Dock.Left);
                result.Children.Add(label);

                return result;
            }
        );
        return new(cell, edit);
    }
    protected override void Configure(TreeGridTemplateColumn column, PopupEditor editor)
    {
        var (cell, edit) = GetTemplates(column, editor);
        column.CellTemplate = cell;
        column.EditTemplate = edit;
        column.SetCellBoundValue = false;
    }

    protected override void Configure(GridTemplateColumn column, PopupEditor editor)
    {
        var (cell, edit) = GetTemplates(column, editor);
        column.CellTemplate = cell;
        column.EditTemplate = edit;
        column.SetCellBoundValue = false;
    }

    public DynamicGridPopupColumn(DynamicGridColumn definition) : base(definition)
    {
    }
}
