using InABox.Configuration;
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;

namespace InABox.DynamicGrid;

/// <summary>
/// A component which loads a custom set of columns from the database.
/// </summary>
public class DynamicGridCustomColumnsComponent<T>
    where T : BaseObject, new()
{
    private readonly DynamicGrid<T> Grid;

    public string? Tag { get; set; }

    public DynamicGridCustomColumnsComponent(DynamicGrid<T> grid, string? tag)
    {
        Grid = grid;
        Tag = tag;
    }

    public DynamicGridColumns LoadColumns()
    {
        var tag = GetTag(Grid.IsDirectEditMode());
        
        var user = Task.Run(() => new UserConfiguration<DynamicGridColumns>(tag).Load());
        var global = Task.Run(() => new GlobalConfiguration<DynamicGridColumns>(tag).Load());
        Task.WaitAll(user, global);

        var columns = user.Result.Any() ? user.Result : global.Result;

        if (!columns.Any())
            columns = Grid.GenerateColumns();

        columns.RemoveAll(x =>
        {
            if (x.ColumnName.IsNullOrWhiteSpace()) return true;

            var prop = DatabaseSchema.Property(typeof(T), x.ColumnName);
            if (prop is null || prop.Editor is NullEditor) return true;

            x.Editor = prop.Editor;
            return false;
        });

        return columns;
    }

    public void SaveColumns(DynamicGridColumns columns)
    {
        var tag = GetTag(Grid.IsDirectEditMode());
        new UserConfiguration<DynamicGridColumns>(tag).Save(columns);
    }

    private string GetTag(bool directEdit)
    {
        var tag = Tag ?? typeof(T).Name;
        if (directEdit)
            tag += ":DirectEdit";
        return tag;
    }

    public void LoadColumnsMenu(ContextMenu menu)
    {
        menu.AddSeparatorIfNeeded();
        menu.AddItem("Reset Columns to Default", null, ResetColumnsClick);
        if (Security.IsAllowed<CanSetDefaultColumns>())
        {
            menu.AddItem("Reset Columns to System Default", null, ResetColumnsToSystemClick);
            menu.AddSeparator();
            menu.AddItem("Mark Columns as Default", null, UpdateDefaultColumnsClick);
        }
    }

    private void ResetColumnsToSystemClick()
    {
        SaveColumns(Grid.GenerateColumns());
        Grid.Refresh(true, true);
    }

    private void ResetColumnsClick()
    {
        Grid.VisibleColumns.Clear();
        SaveColumns(Grid.VisibleColumns);
        Grid.Refresh(true, true);
    }

    private void UpdateDefaultColumnsClick()
    {
        var tag = GetTag(Grid.IsDirectEditMode());
        new GlobalConfiguration<DynamicGridColumns>(tag).Save(Grid.VisibleColumns);
        new UserConfiguration<DynamicGridColumns>(tag).Delete();
        Grid.Refresh(true, true);
    }
}
