using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using InABox.Core;
using InABox.WPF;
using InABox.Wpf;

namespace InABox.DynamicGrid
{
    /// <summary>
    ///     Interaction logic for MasterList.xaml
    /// </summary>
    public partial class MasterList : ThemableWindow
    {
        private bool AllItems;
        private readonly bool AllowAllItems = true;

        private bool bLoaded;
        private readonly IDynamicGrid grid;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="groupby"></param>
        /// <param name="selectedgroup"></param>
        /// <param name="allowallitems">Show an "All Items" entry at tge top of the Groups List Box</param>
        /// <param name="dataGrid">If null, finds a DynamicDataGrid of the specified entity type. 
        /// Otherwise, MasterList uses this parameter as the DynamicGrid type</param>
        public MasterList(Type type, string? groupby = null, string? selectedgroup = null, bool allowallitems = false, Type? dataGrid = null,
            IDynamicGrid? dynamicGrid = null)
        {
            InitializeComponent();
            Type = type;
            AllowAllItems = allowallitems;
            SelectedGroup = selectedgroup;
            CurrentGroup = selectedgroup;
            GroupBy = groupby;

            if(dynamicGrid is null)
            {
                if(dataGrid == null)
                {
                    dataGrid = DynamicGridUtils.FindDynamicGrid(typeof(DynamicDataGrid<>), type);
                }
                grid = (Activator.CreateInstance(dataGrid) as IDynamicGrid) ?? throw new Exception($"Invalid Grid Type {dataGrid}");
            }
            else
            {
                grid = dynamicGrid;
            }

            grid.Margin = new Thickness(5, 5, 5, 5);
            ((DependencyObject)grid).SetValue(Grid.ColumnProperty, 1);
            ((DependencyObject)grid).SetValue(Grid.RowProperty, 0);

            layoutGrid.Children.Add((UIElement)grid);

            DataModelType = typeof(AutoDataModel<>).MakeGenericType(type);

            grid.Reconfigure(options =>
            {
                options.SelectColumns = true;
                options.FilterRows = true;
                options.ShowHelp = true;

                if (DataModelType != null)
                    options.Print = true;
            });

            if (!string.IsNullOrWhiteSpace(GroupBy))
                grid.AddHiddenColumn(GroupBy);

            grid.OnPrintData += PrintData;

            grid.AfterRefresh += Grid_AfterReload;

            grid.OnFilterRecord += Grid_OnFilterRecord;

            grid.OnCreateItem += Grid_OnCreateItem;

            grid.Refresh(true, true);
        }

        public Type Type { get; set; }

        private Type DataModelType { get; }

        public object? CurrentGroup { get; set; }
        public string? GroupBy { get; set; }
        public string? SelectedGroup { get; set; }
        public List<Tuple<string, object?, BitmapImage>> GroupList { get; private set; }

        private void Grid_AfterReload(object sender, AfterRefreshEventArgs args)
        {
            if (bLoaded)
                return;

            if (!string.IsNullOrEmpty(GroupBy))
            {
                CoreTable lookups = null;
                var col = grid.MasterColumns.First(x => x.ColumnName.Equals(GroupBy)).Editor as ILookupEditor;
                if (col != null)
                    lookups = col.Values(GroupBy);
                //grid.ConfigureColumns(grid.MasterColumns, true);
                //grid.AddHiddenColumn(GroupBy);

                GroupList = new List<Tuple<string, object?, BitmapImage>>();
                if (AllowAllItems)
                    GroupList.Add(new Tuple<string, object?, BitmapImage>("All Items", null, Wpf.Resources.doc_misc.AsBitmapImage()));

                var column = grid.MasterColumns.Where(x => x.ColumnName.Equals(GroupBy)).FirstOrDefault();
                if (column != null)
                    foreach (var row in grid.Data.Rows)
                    {
                        var entry = row[GroupBy];
                        string display = "Unassigned";
                        if (entry != null)
                        {
                            display = entry.ToString()!;
                            if (lookups != null)
                            {
                                var lookup = lookups.Rows.FirstOrDefault(r => r[GroupBy] != null && r[GroupBy].Equals(entry));
                                if (lookup != null)
                                    display = lookup.Get<string>("Display");
                            }
                        }

                        if (!GroupList.Any(x => (x.Item1 == null && display == "") || (x.Item1 != null && x.Item1.Equals(display))))
                            GroupList.Add(new Tuple<string, object?, BitmapImage>(entry != null ? display : "Unassigned", entry,
                                Wpf.Resources.doc_misc.AsBitmapImage()));
                    }

                //foreach (var key in column.Lookups.Keys)
                //    GroupList.Add(new Tuple<string, string, BitmapImage>(column.Lookups[key].ToString(), key.ToString(), Wpf.Resources.edit.AsBitmapImage()));
                if (!string.IsNullOrWhiteSpace(SelectedGroup))
                    if (!GroupList.Any(x => Equals(x.Item2, SelectedGroup)))
                        GroupList.Add(new Tuple<string, object?, BitmapImage>(SelectedGroup, SelectedGroup,
                            Wpf.Resources.doc_misc.AsBitmapImage()));
                GroupList = GroupList.OrderBy(x => (x.Item1 == "All Items" ? "0" : x.Item1 == "Unassigned" ? "1" : "2") + x.Item1).ToList();
                Groups.ItemsSource = GroupList;

                if (string.IsNullOrEmpty(SelectedGroup))
                {
                    CurrentGroup = "";
                    Groups.Visibility = Visibility.Visible;
                }
                else
                {
                    CurrentGroup = SelectedGroup;
                    Groups.Visibility = Visibility.Collapsed;
                }
            }
            else
            {
                Groups.Visibility = Visibility.Collapsed;
            }

            //grid.Refresh(true, true);


            bLoaded = true;

            var item = GroupList != null
                ? GroupList.FirstOrDefault(x => (SelectedGroup == null && x.Item2 == null) || (x.Item2 != null && x.Item2.Equals(SelectedGroup)))
                : null;
            if (!AllowAllItems && item == null)
                item = GroupList?.FirstOrDefault();

            AllItems = AllowAllItems && item == null;
            Groups.SelectedIndex = item != null ? GroupList.IndexOf(item) : 0;
            Title = Type.Name + " Master List" + (item == null ? "" : " - " + item.Item1);
            Groups.Focus();
        }

        private void PrintData(object sender)
        {
            var filtertype = typeof(Filter<>).MakeGenericType(Type);
            var filter = Activator.CreateInstance(filtertype, "ID") as IFilter;
            filter.Property = "ID";
            filter.Operator = Operator.InList;
            filter.Value = grid.SelectedRows.Select(r => r.Get<Guid>("ID")).ToArray();
            var model = Activator.CreateInstance(DataModelType, filter) as DataModel;
        }

        private void Grid_OnCreateItem(object sender, object item)
        {
            if (!string.IsNullOrEmpty(GroupBy) && CurrentGroup != null)
                CoreUtils.SetPropertyValue(item, GroupBy, CurrentGroup);
        }

        private bool Grid_OnFilterRecord(CoreRow row)
        {
            if (AllItems)
                return true;
            var result = GroupBy == null || CurrentGroup == null || Equals(CurrentGroup, row[GroupBy]);
            return result; // ((CurrentGroup == null) && (row[GroupBy] == null)) || ((CurrentGroup != null) && (CurrentGroup.Equals(row[GroupBy])));
        }

        private void Groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!bLoaded)
                return;

            var newCurrentGroup = CurrentGroup;
            if (e.AddedItems.Count == 0 || Groups.SelectedIndex == 0)
            {
                AllItems = AllowAllItems;
                newCurrentGroup = GroupList.Any() ? GroupList.First().Item2 : null;
            }
            else
            {
                AllItems = false;
                var selected = (Tuple<string, object, BitmapImage>)e.AddedItems[0];
                newCurrentGroup = selected.Item2;
            }

            if (!Equals(newCurrentGroup, CurrentGroup))
            {
                CurrentGroup = newCurrentGroup;
                grid.Refresh(false, false);
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            var center = new Point(Left + Width / 2, Top + Height / 2);

            var screen = WpfScreen.GetScreenFrom(this);
            var maxwidth = (int)screen.WorkingArea.Width - 200;
            ((FrameworkElement)grid).Width = Math.Min(Math.Max(grid.DesiredWidth(),450),maxwidth);
            
            // var DesiredWidth = Math.Max(600, grid.DesiredWidth());
            // if (DesiredWidth > maxwidth)
            //     DesiredWidth = maxwidth;
            // if (DesiredWidth > Width)
            //     Width = DesiredWidth;
            // if (!string.IsNullOrEmpty(GroupBy))
            //     Width += Groups.DesiredSize.Width + 45.0F;
            //
            // var maxheight = (int)screen.WorkingArea.Height - 200;
            // var DesiredHeight = (int)(Width * 0.75);
            // if (DesiredHeight > maxheight)
            //     DesiredHeight = maxheight;
            // if (DesiredHeight > Height)
            //     Height = DesiredHeight;
            
            Left = center.X - Width / 2;
            Top = center.Y - Height / 2;

        }
    }
}