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

namespace InABox.DynamicGrid;

public class DynamicImportMappingGrid : DynamicGrid<ImportMapping>
{
    private readonly BitmapImage create = Wpf.Resources.tick.AsBitmapImage();

    private readonly BitmapImage key = Wpf.Resources.key.AsBitmapImage();

    private readonly BitmapImage restrict = Wpf.Resources.warning.AsBitmapImage();

    public DynamicImportMappingGrid()
    {
        UniqueCode = "";

        HideBlank = false;

        Items = new List<ImportMapping>();
    }

    protected override void Init()
    {
        base.Init();
        ActionColumns.Add(new DynamicImageColumn(KeyImage, KeyAction) { Position = DynamicActionColumnPosition.Start, ToolTip = KeyToolTip });
        HiddenColumns.Add(x => x.Key);

        ActionColumns.Add(new DynamicImageColumn(LookupImage, LookupAction) { ToolTip = LookupToolTip });
        HiddenColumns.Add(x => x.Lookup);
    }

    protected override void DoReconfigure(DynamicGridOptions options)
    {
        base.DoReconfigure(options);
        options.RecordCount = true;
        options.DirectEdit = true;
    }

    public List<ImportMapping> Items { get; }

    public string UniqueCode { get; set; }

    public bool HideBlank { get; set; }

    public override void DeleteItems(params CoreRow[] rows)
    {
        var deletes = new List<ImportMapping>();
        foreach (var row in rows)
            deletes.Add(Items[row.Index]);
        Items.RemoveAll(x => deletes.Contains(x));
    }

    public override ImportMapping LoadItem(CoreRow row)
    {
        return Items[row.Index];
    }

    protected override void Reload(
        Filters<ImportMapping> criteria, Columns<ImportMapping> columns, ref SortOrder<ImportMapping>? sort, 
        CancellationToken token, Action<CoreTable?, Exception?> action)
    {
        //Lookups.Clear();
        var result = new CoreTable();
        result.LoadColumns(typeof(ImportMapping));
        if (HideBlank)
            result.LoadRows(Items.Where(x => !string.IsNullOrWhiteSpace(x.Field) || !string.IsNullOrWhiteSpace(x.Constant)));
        else
            result.LoadRows(Items);
        foreach(var item in Items)
        {
            if(!item.Field.IsNullOrWhiteSpace() && !ImportFieldGenerator.Fields.Contains(item.Field))
            {
                item.Field = "";
            }
        }
        action.Invoke(result, null);
    }

    public override void SaveItem(ImportMapping item)
    {
        if (!Items.Contains(item))
            Items.Add(item);
    }

    private FrameworkElement? KeyToolTip(DynamicActionColumn column, CoreRow? row)
    {
        var result = "";
        if (row == null)
            result = "This column is used to indicate which fields form the unique key imported records";
        else
        {
            var key = row.Get<ImportMapping, bool>(x => x.Key);
            result = key
                ? "This field forms part (or all) of the unique key for imported records"
                : "";
        }
        return column.TextToolTip(result);
    }

    private FrameworkElement? LookupToolTip(DynamicActionColumn column, CoreRow? row)
    {
        var result = "";
        if (row == null)
            result = "This column determines whether or not lookup values are automatically created as required, or cause the import to fail.";
        else
        {
            var lookup = row.Get<ImportMapping, ImportLookupType>(x => x.Lookup);
            result = lookup == ImportLookupType.None
                ? ""
                : lookup == ImportLookupType.Create
                    ? "Create Lookup Values as required"
                    : "Restrict Importing for invalid / non-existent Lookup Values";
        }
        return column.TextToolTip(result);
    }

    public void Reset()
    {
        foreach (var item in Items)
        {
            item.Key = false;
            item.Field = "";
            item.Constant = "";
            item.Lookup = item.Lookup == ImportLookupType.Create ? ImportLookupType.Restrict : item.Lookup;
        }

        Refresh(false, true);
    }

    public void MatchFields()
    {
        foreach (var item in Items)
        {
            var field = ImportFieldGenerator.Fields.FirstOrDefault(x => String.Equals(item.Property.ToUpper(), x.ToUpper()));
            if (!String.IsNullOrWhiteSpace(field))
            {
                item.Field = field;
                if (item.Property.Equals(UniqueCode))
                    item.Key = true;
            }
            else
            {
                item.Key = false;
                item.Field = "";
                item.Constant = "";
                item.Lookup = item.Lookup == ImportLookupType.Create ? ImportLookupType.Restrict : item.Lookup;
            }
        }

        Refresh(false, true);
    }

    private BitmapImage? KeyImage(CoreRow? arg)
    {
        if (arg == null)
            return key;
        return arg.Get<ImportMapping, bool>(x => x.Key) ? key : null;
    }

    private bool KeyAction(CoreRow? arg)
    {
        if (arg == null)
            return false;
        var item = Items[arg.Index];
        if (string.IsNullOrWhiteSpace(item.Field) && string.IsNullOrWhiteSpace(item.Constant))
        {
            if (item.Key)
            {
                item.Key = false;
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            item.Key = !item.Key;
            return true;
        }
    }

    private BitmapImage? LookupImage(CoreRow? arg)
    {
        if (arg == null)
            return restrict;

        var item = Items.FirstOrDefault(x => x.Property.Equals(arg.Get<ImportMapping, string>(c => c.Property)));

        if (item == null)
            return null;

        if (string.IsNullOrWhiteSpace(item.Field) && string.IsNullOrWhiteSpace(item.Constant))
            return null;

        return item.Lookup == ImportLookupType.Create
            ? create
            : item.Lookup == ImportLookupType.Restrict
                ? restrict
                : null;
    }

    private bool LookupAction(CoreRow? arg)
    {
        if (arg == null)
            return false;

        var property = arg.Get<ImportMapping, string>(c => c.Property);
        var item = Items.FirstOrDefault(x => x.Property.Equals(property));

        if (item == null || (string.IsNullOrWhiteSpace(item.Field) && string.IsNullOrWhiteSpace(item.Constant)))
            return false;

        if (item.Lookup == ImportLookupType.Restrict)
            item.Lookup = ImportLookupType.Create;
        else if (item.Lookup == ImportLookupType.Create)
            item.Lookup = ImportLookupType.Restrict;
        else
            return false;

        return true;
    }
}