using InABox.Core;
using InABox.Wpf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace InABox.DynamicGrid
{
    /// <summary>
    /// Interaction logic for SubQueryWindow.xaml
    /// </summary>
    public partial class SubQueryNodePopup : ThemableWindow
    {
        private string[] ColumnNames = [];

        public Type? QueryType
        {
            get => (Type.SelectedItem as TypeEntry)?.Type;
            set
            {
                if (value == (Type.SelectedItem as TypeEntry)?.Type)
                    return;
                Type.SelectedIndex = -1;
                foreach (var (item, i) in Type.Items.Cast<object>().Select((x, i) => new Tuple<object, int>(x, i)))
                {
                    if ((item as TypeEntry)?.Type == value)
                    {
                        Type.SelectedIndex = i;
                        break;
                    }
                }
                UpdateQueryType();
            }
        }

        private string? _column;
        public string? Column
        {
            get => _column;
            set
            {
                _column = value;
                Property.Content = value.IsNullOrWhiteSpace() ? " " : value;
            }
        }
        public IFilter? Filter
        {
            get => FilterNode?.GetFilter();
            set
            {
                if (FilterNode != null)
                {
                    Grid.Children.Remove(FilterNode);
                }
                if (value != null && QueryType is not null)
                {
                    FilterNode = Activator.CreateInstance(typeof(FilterNode<>).MakeGenericType(QueryType), value, FilterNodeType.ROOT, Configuration) as BaseFilterNode;
                    FilterNode.SetValue(Grid.RowProperty, 2);
                    FilterNode.SetValue(Grid.ColumnProperty, 0);
                    FilterNode.SetValue(Grid.ColumnSpanProperty, 2);
                    Grid.Children.Add(FilterNode);
                }
                else
                {
                    FilterNode = null;
                }
            }
        }

        private FilterEditorConfiguration Configuration;

        private BaseFilterNode? FilterNode;

        public SubQueryNodePopup(FilterEditorConfiguration configuration)
        {
            InitializeComponent();

            if (_types == null)
            {
                _types = CoreUtils.TypeList(x =>
                            !x.IsAbstract
                            && !x.IsGenericType
                            && x.IsSubclassOf(typeof(Entity))).ToList();
                _types.Sort((a, b) => a.Name.CompareTo(b.Name));
            }
            foreach (var type in _types)
            {
                Type.Items.Add(new TypeEntry(type));
            }
            Type.SelectionChanged += Type_SelectionChanged;
            Configuration = configuration;
        }

        private void Type_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UpdateQueryType();
        }

        private void UpdateQueryType()
        {
            var type = (Type.SelectedItem as TypeEntry)?.Type;
            Column = null;

            if(type != null)
            {
                Filter = Activator.CreateInstance(typeof(Filter<>).MakeGenericType(type)) as IFilter;
                Property.IsEnabled = true;

                var properties = DatabaseSchema.Properties(type)
                    .Where(x => x.IsSerializable)
                    .Select(x => x.Name)
                    .ToList();
                properties.Sort();
                ColumnNames = properties.ToArray();
            }
            else
            {
                Filter = null;
                Property.IsEnabled = false;
            }
        }

        private static List<Type>? _types;
        private class TypeEntry
        {
            public Type Type { get; set; }

            public TypeEntry(Type type)
            {
                Type = type;
            }

            public override string ToString()
            {
                return Type.Name;
            }
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
            Close();
        }

        private void OK_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
            Close();
        }

        private void Property_Click(object sender, RoutedEventArgs e)
        {
            var type = (Type.SelectedItem as TypeEntry)?.Type;

            if(type is not null && DynamicGridColumnNameSelectorGrid.SelectColumnName(type, ColumnNames, out var value))
            {
                Column = value.IsNullOrWhiteSpace() ? null : value;
            }
        }
    }
}
