using InABox.Clients;
using InABox.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace InABox.DynamicGrid;
///
/// Defines a common interface for dealing with grids like
/// or , which display s, but do not load them necessarily from the database,
/// instead keeping them in memory.
///
/// This interface then allows other functions, like
/// , to work based on and manage our column handling better.
///
///
public interface IDynamicMemoryEntityGrid
where T : Entity, IRemotable, IPersistent, new()
{
///
/// A set of columns representing which columns have been loaded from the database.
///
///
/// This is used to refresh the data when the columns change.
///
/// It is if no data has been loaded from the database (that is, the data was gotten from
/// a page data handler instead.)
///
public HashSet? LoadedColumns { get; }
public IEnumerable Items { get; }
}
public static class DynamicMemoryEntityGridExtensions
{
public static void EnsureColumns(this IDynamicMemoryEntityGrid grid, Columns columns)
where T : Entity, IRemotable, IPersistent, new()
{
RequireColumns(grid, columns);
LoadForeignProperties(grid, columns);
}
///
/// Load the properties of any s on this where the is not .
/// This allows us to populate columns of transient objects, as long as they are linked by the ID. What this actually then does is query each
/// linked table with the required columns.
///
///
public static void LoadForeignProperties(this IDynamicMemoryEntityGrid grid, Columns columns)
where T : Entity, IRemotable, IPersistent, new()
{
grid.Items.LoadForeignProperties(columns);
}
public static void RequireColumns(this IDynamicMemoryEntityGrid grid, Columns columns)
where T : Entity, IRemotable, IPersistent, new()
{
if (grid.LoadedColumns is null) return;
// Figure out which columns we still need.
var newColumns = columns.Where(x => !grid.LoadedColumns.Contains(x.Property)).ToColumns(ColumnTypeFlags.None);
if (newColumns.Count > 0 && typeof(T).GetCustomAttribute() is null)
{
var data = Client.Query(
new Filter(x => x.ID).InList(grid.Items.Select(x => x.ID).Where(x => x != Guid.Empty).ToArray()),
// We also need to add ID, so we know which item to fill.
newColumns.Add(x => x.ID));
foreach (var row in data.Rows)
{
var item = grid.Items.FirstOrDefault(x => x.ID == row.Get(y => y.ID));
if (item is not null)
{
row.FillObject(item, overrideExisting: false);
}
}
// Remember that we have now loaded this data.
foreach (var column in newColumns)
{
grid.LoadedColumns.Add(column.Property);
}
}
}
}