using System;
using System.Collections.Generic;
using System.Linq;
using InABox.Clients;
using System.Diagnostics.CodeAnalysis;
namespace InABox.Core
{
public interface IDigitalFormReportDataModel
{
public DigitalFormVariable[]? Variables { get; set; }
void AddFormData(Guid formInstanceID, DFLoadStorage storage);
}
///
///
///
/// Should always be an EntityForm<,>
public class DigitalFormReportDataModel : AutoDataModel, IDigitalFormReportDataModel
where T : Entity, IRemotable, IPersistent, IDigitalFormInstance, new()
{
private Guid? FormId { get; set; } = null;
private CoreTable? FormDataTable { get; set; } = null;
private Dictionary FormData { get; set; } = new Dictionary();
//private DigitalFormVariable[]? _variables = null;
public DigitalFormVariable[]? Variables { get; set; }
public DigitalFormReportDataModel(Filter filter, Guid? formId = null) : base(filter)
{
FormId = formId;
}
public override string Name => "Digital Form Reports";
public void AddFormData(Guid formInstanceID, DFLoadStorage storage)
{
FormData.Add(formInstanceID, storage);
}
protected override void CheckRequiredTables(List requiredtables)
{
base.CheckRequiredTables(requiredtables);
requiredtables.Add(TableName());
}
private void LoadFormDataTable(Guid formID)
{
var formDataTable = new CoreTable();
formDataTable.Columns.Add(new CoreColumn
{
ColumnName = "Parent.ID",
DataType = typeof(Guid)
});
Variables ??= new Client().Load(new Filter(x => x.Form.ID).IsEqualTo(formID));
foreach (var variable in Variables)
{
var columns = variable.GetDisplayColumns().ToArray();
foreach (var column in columns)
formDataTable.Columns.Add(column);
}
FormDataTable = formDataTable;
AddTable("Form_Data", formDataTable, isdefault: true);
LinkTable(typeof(T), "ID", "Form_Data", "Parent.ID");
}
private void LoadFormDataIntoRow(CoreRow row, DFLoadStorage data)
{
foreach(var variable in Variables!)
{
var value = variable.Deserialize(data.GetEntry(variable.Code));
foreach(var (k, v) in variable.GetDisplayValues(value))
{
row[k] = v;
}
}
}
protected override void AfterLoad(IEnumerable requiredtables)
{
base.AfterLoad(requiredtables);
if(FormDataTable == null)
{
LoadFormDataTable(FormId ?? ExtractValues(x => x.Form.ID).FirstOrDefault());
}
var idList = ExtractValues(x => x.ID);
var jsonLists = ExtractValues(x => x.FormData, false).ToList();
var blobLists = ExtractValues(x => x.BlobData, false).ToList();
for(var i = 0; i < jsonLists.Count; ++i)
{
if (!FormData.TryGetValue(idList[i], out var formData))
{
var json = jsonLists[i];
var blobJSON = blobLists[i];
formData = DigitalForm.DeserializeFormData(json, blobJSON);
}
var formRow = FormDataTable!.NewRow();
formRow["Parent.ID"] = idList[i];
if (formData != null) LoadFormDataIntoRow(formRow, formData);
FormDataTable.Rows.Add(formRow);
}
Load(typeof(CoreTable), FormDataTable!, requiredtables, "Form_Data");
}
public string? EvaluateExpression(string expression)
{
if (string.IsNullOrWhiteSpace(expression))
return null;
Dictionary variables = new Dictionary();
var formrow = FormDataTable.Rows.FirstOrDefault();
foreach (var column in FormDataTable.Columns)
variables[$"Data.{column.ColumnName}"] = formrow?[column.ColumnName];
var instancetable = GetTable();
var instancerow = instancetable.Rows.FirstOrDefault();
foreach (var column in instancetable.Columns)
variables[$"Form.{column.ColumnName}"] = instancerow?[column.ColumnName];
var inter = typeof(T)
.GetInterfaces()
.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDigitalFormInstance<>));
if (inter != null)
{
var link = inter.GenericTypeArguments[0];
var entityLinkDef = link.GetSuperclassDefinition(typeof(EntityLink<>));
if (entityLinkDef != null)
{
var entityType = entityLinkDef.GenericTypeArguments[0];
var parenttablename = $"{DataModel.TableName(typeof(T))}_{DataModel.TableName(entityType)}";
var entitytable = GetDataModelTable(parenttablename);
if (entitytable != null)
{
foreach (var column in entitytable.Table.Columns)
variables[$"{entityType.EntityName().Split('.').Last()}.{column.ColumnName}"] =
instancerow?[column.ColumnName];
}
}
}
var exp = new CoreExpression(expression);
return exp.Evaluate(variables)?.ToString();
}
}
}