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

namespace InABox.DynamicGrid;

public class DynamicEntityFormGrid<TForm, TEntity, TEntityLink> : DynamicDataGrid<TForm>
    where TForm : EntityForm<TEntity, TEntityLink, TForm>, new()
    where TEntity : Entity
    where TEntityLink : BaseObject, IEntityLink<TEntity>, new()
{
    protected virtual TEntity Entity { get; set; }

    public bool EditOnAdd { get; set; }

    public DynamicEntityFormGrid()
    {
        OnBeforeSave += BeforeSave;
        OnCustomiseEditor += DynamicEntityFormGrid_OnCustomiseEditor;

        ActionColumns.Add(new DynamicImageColumn(EditImage, EditClick));
        if (DynamicGridUtils.PreviewReport != null)
            ActionColumns.Add(new DynamicImageColumn(PrintImage, PrintClick));
        HiddenColumns.Add(x => x.FormCompleted);
        HiddenColumns.Add(x => x.Form.ID);
    }

    public DynamicEntityFormGrid(TEntity entity) : this()
    {
        Entity = entity;
    }

    private void DynamicEntityFormGrid_OnCustomiseEditor(IDynamicEditorForm sender, TForm[]? items, DynamicGridColumn column, BaseEditor editor)
    {
        if(column.ColumnName == "Form.ID")
        {
            editor.Editable = Editable.Disabled;
        }
    }

    protected override void DoAdd(bool openEditorOnDirectEdit = false)
    {
        var filter = LookupFactory.DefineChildFilter<TEntity, DigitalForm>(new TEntity[] { Entity })
            ?? LookupFactory.DefineLookupFilter<TForm, DigitalForm, DigitalFormLink>(x => x.Form, Array.Empty<TForm>());
        var columns = LookupFactory.DefineLookupColumns<TForm, DigitalForm, DigitalFormLink>(x => x.Form);

        var select = new MultiSelectDialog<DigitalForm>(
            filter,
            columns.Add(x => x.Description),
            false);

        if (select.ShowDialog() == true)
        {
            var digitalForm = select.Items().FirstOrDefault();
            if(digitalForm is not null)
            {
                var form = new TForm
                {
                    Description = digitalForm.Description
                };
                form.Form.CopyFrom(digitalForm);
                form.Parent.ID = Entity.ID;

                var refresh = false;
                if (EditOnAdd)
                {
                    form.FormStarted = DateTime.Now;
                    if (DynamicFormEditWindow.EditDigitalForm(form, out var dataModel))
                    {
                        dataModel.Update(null);
                        refresh = true;
                    }
                }
                else
                {
                    SaveItem(form);
                    refresh = true;
                }

                if (refresh)
                {
                    Refresh(false, true);
                    DoChanged();
                }
            }
        }
    }

    public override TForm CreateItem()
    {
        var result = base.CreateItem();
        result.Parent.ID = Entity.ID;
        return result;
    }

    protected override void Reload(
        Filters<TForm> criteria, Columns<TForm> columns, ref SortOrder<TForm>? sort, 
        CancellationToken token, Action<CoreTable?, Exception?> action)
    {
        criteria.Add(new Filter<TForm>(x => x.Parent.ID).IsEqualTo(Entity.ID));
        base.Reload(criteria, columns, ref sort, token, action);
    }

    private void BeforeSave(IDynamicEditorForm editor, BaseObject[] items)
    {
        foreach(var item in items.Cast<TForm>())
        {
            item.Parent.ID = Entity.ID;
        }
    }

    private BitmapImage PrintImage(CoreRow? arg)
    {
        return Wpf.Resources.print.AsBitmapImage();
    }

    private bool PrintClick(CoreRow? arg)
    {
        if (arg is null) return false;

        var formid = arg.Get<TForm, Guid>(x => x.Form.ID);
        var model = new DigitalFormReportDataModel<TForm>(new Filter<TForm>("Parent.ID").IsEqualTo(Entity.ID), formid);
        var section = formid.ToString();

        // TODO: This is a hack
        DynamicGridUtils.PrintMenu?.Invoke(null, section, model, true);

        return false;
    }

    private BitmapImage EditImage(CoreRow? arg)
    {
        if (arg == null)
            return Wpf.Resources.pencil.AsBitmapImage();
        var completed = arg.Get<TForm, DateTime>(x => x.FormCompleted);
        return completed.IsEmpty() ? Wpf.Resources.pencil.AsBitmapImage() : Wpf.Resources.view.AsBitmapImage();
    }

    private bool EditClick(CoreRow? arg)
    {
        if (arg is null) return false;

        var item = LoadItem(arg);

        var form = new Client<TForm>()
            .Query(
                new Filter<TForm>(x => x.ID).IsEqualTo(item.ID),
                Columns.None<TForm>().Add(x => x.ID)
                    .Add(x => x.FormData)
                    .Add(x => x.BlobData)
                    .Add(x => x.FormCompleted)
                    .Add(x => x.FormCompletedBy.ID)
                    .Add(x => x.Form.ID)
                    .Add(x => x.Parent.ID))
            .Rows.FirstOrDefault()?.ToObject<TForm>();
        if (form is null) return false;

        if (DynamicFormEditWindow.EditDigitalForm(form, out var dataModel))
        {
            dataModel.Update(null);
            return true;
        }
        return false;
    }
}
