using System.Collections.Generic;
#if NET40_OR_GREATER || NETCOREAPP
using System.Threading.Tasks;
#endif
using SabreTools.Core.Tools;
using SabreTools.DatItems;
using SabreTools.DatItems.Formats;
namespace SabreTools.DatFiles
{
public partial class DatFile
{
#region Removal
///
/// Remove fields indicated by the three input lists
///
public void ApplyRemovals(List headerFieldNames, List machineFieldNames, Dictionary> itemFieldNames)
{
// Remove DatHeader fields
if (headerFieldNames.Count > 0)
RemoveHeaderFields(headerFieldNames);
// Remove DatItem and Machine fields
if (machineFieldNames.Count > 0 || itemFieldNames.Count > 0)
{
ApplyRemovalsItemDictionary(machineFieldNames, itemFieldNames);
ApplyRemovalsItemDictionaryDB(machineFieldNames, itemFieldNames);
}
}
///
/// Apply removals to the item dictionary
///
private void ApplyRemovalsItemDictionary(List machineFieldNames, Dictionary> itemFieldNames)
{
#if NET452_OR_GREATER || NETCOREAPP
Parallel.ForEach(Items.Keys, Core.Globals.ParallelOptions, key =>
#elif NET40_OR_GREATER
Parallel.ForEach(Items.Keys, key =>
#else
foreach (var key in Items.Keys)
#endif
{
List? items = Items[key];
if (items == null)
#if NET40_OR_GREATER || NETCOREAPP
return;
#else
continue;
#endif
for (int j = 0; j < items.Count; j++)
{
RemoveFields(items[j], machineFieldNames, itemFieldNames);
}
#if NET40_OR_GREATER || NETCOREAPP
});
#else
}
#endif
}
///
/// Apply removals to the item dictionary
///
private void ApplyRemovalsItemDictionaryDB(List machineFieldNames, Dictionary> itemFieldNames)
{
#if NET452_OR_GREATER || NETCOREAPP
Parallel.ForEach(ItemsDB.SortedKeys, Core.Globals.ParallelOptions, key =>
#elif NET40_OR_GREATER
Parallel.ForEach(ItemsDB.SortedKeys, key =>
#else
foreach (var key in ItemsDB.SortedKeys)
#endif
{
var items = ItemsDB.GetItemsForBucket(key);
if (items == null)
#if NET40_OR_GREATER || NETCOREAPP
return;
#else
continue;
#endif
for (int j = 0; j < items.Length; j++)
{
RemoveFields(items[j].Item2, machineFieldNames, itemFieldNames);
}
#if NET40_OR_GREATER || NETCOREAPP
});
#else
}
#endif
}
///
/// Remove fields with given values
///
private void RemoveHeaderFields(List headerFieldNames)
{
// If we have an invalid input, return
if (Header == null || headerFieldNames.Count == 0)
return;
foreach (var fieldName in headerFieldNames)
{
Header.RemoveField(fieldName);
}
}
///
/// Remove fields with given values
///
private static void RemoveFields(Machine? machine, List machineFieldNames)
{
// If we have an invalid input, return
if (machine == null || machineFieldNames.Count == 0)
return;
foreach (var fieldName in machineFieldNames)
{
machine.RemoveField(fieldName);
}
}
///
/// Remove fields with given values
///
/// DatItem to remove fields from
private static void RemoveFields(DatItem? datItem, List machineFieldNames, Dictionary> itemFieldNames)
{
if (datItem == null)
return;
#region Common
// Handle Machine fields
var machine = datItem.GetFieldValue(DatItem.MachineKey);
if (machineFieldNames.Count > 0 && machine != null)
RemoveFields(machine, machineFieldNames);
// If there are no field names, return
if (itemFieldNames == null || itemFieldNames.Count == 0)
return;
// If there are no field names for this type or generic, return
string? itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue().AsStringValue();
if (itemType == null || (!itemFieldNames.ContainsKey(itemType) && !itemFieldNames.ContainsKey("item")))
return;
// Get the combined list of fields to remove
var fieldNames = new HashSet();
if (itemFieldNames.ContainsKey(itemType))
fieldNames.IntersectWith(itemFieldNames[itemType]);
if (itemFieldNames.ContainsKey("item"))
fieldNames.IntersectWith(itemFieldNames["item"]);
// If the field specifically contains Name, set it separately
if (fieldNames.Contains(Models.Metadata.Rom.NameKey))
datItem.SetName(null);
#endregion
#region Item-Specific
// Handle unnested removals first
foreach (var datItemField in fieldNames)
{
datItem.RemoveField(datItemField);
}
// Handle nested removals
switch (datItem)
{
case Adjuster adjuster: RemoveFields(adjuster, itemFieldNames); break;
case Configuration configuration: RemoveFields(configuration, itemFieldNames); break;
case ConfSetting confSetting: RemoveFields(confSetting, itemFieldNames); break;
case Device device: RemoveFields(device, itemFieldNames); break;
case DipSwitch dipSwitch: RemoveFields(dipSwitch, itemFieldNames); break;
case DipValue dipValue: RemoveFields(dipValue, itemFieldNames); break;
case Disk disk: RemoveFields(disk, itemFieldNames); break;
case Input input: RemoveFields(input, itemFieldNames); break;
case Part part: RemoveFields(part, itemFieldNames); break;
case Port port: RemoveFields(port, itemFieldNames); break;
case Rom rom: RemoveFields(rom, itemFieldNames); break;
case Slot slot: RemoveFields(slot, itemFieldNames); break;
}
#endregion
}
///
/// Remove fields with given values
///
/// Adjuster to remove fields from
private static void RemoveFields(Adjuster adjuster, Dictionary> itemFieldNames)
{
var conditions = adjuster.GetFieldValue(Models.Metadata.Adjuster.ConditionKey) ?? [];
foreach (Condition subCondition in conditions)
{
RemoveFields(subCondition, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Configuration to remove fields from
private static void RemoveFields(Configuration configuration, Dictionary> itemFieldNames)
{
var conditions = configuration.GetFieldValue(Models.Metadata.Configuration.ConditionKey) ?? [];
foreach (Condition subCondition in conditions)
{
RemoveFields(subCondition, [], itemFieldNames);
}
var locations = configuration.GetFieldValue(Models.Metadata.Configuration.ConfLocationKey) ?? [];
foreach (ConfLocation subLocation in locations)
{
RemoveFields(subLocation, [], itemFieldNames);
}
var settings = configuration.GetFieldValue(Models.Metadata.Configuration.ConfSettingKey) ?? [];
foreach (ConfSetting subSetting in settings)
{
RemoveFields(subSetting as DatItem, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// ConfSetting to remove fields from
private static void RemoveFields(ConfSetting confsetting, Dictionary> itemFieldNames)
{
var conditions = confsetting.GetFieldValue(Models.Metadata.ConfSetting.ConditionKey) ?? [];
foreach (Condition subCondition in conditions)
{
RemoveFields(subCondition, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Device to remove fields from
private static void RemoveFields(Device device, Dictionary> itemFieldNames)
{
var extensions = device.GetFieldValue(Models.Metadata.Device.ExtensionKey) ?? [];
foreach (Extension subExtension in extensions)
{
RemoveFields(subExtension, [], itemFieldNames);
}
var instances = device.GetFieldValue(Models.Metadata.Device.InstanceKey) ?? [];
foreach (Instance subInstance in instances)
{
RemoveFields(subInstance, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// DipSwitch to remove fields from
private static void RemoveFields(DipSwitch dipSwitch, Dictionary> itemFieldNames)
{
var conditions = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.ConditionKey) ?? [];
foreach (Condition subCondition in conditions)
{
RemoveFields(subCondition, [], itemFieldNames);
}
var locations = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipLocationKey) ?? [];
foreach (DipLocation subLocation in locations)
{
RemoveFields(subLocation, [], itemFieldNames);
}
var dipValues = dipSwitch.GetFieldValue(Models.Metadata.DipSwitch.DipValueKey) ?? [];
foreach (DipValue subValue in dipValues)
{
RemoveFields(subValue as DatItem, [], itemFieldNames);
}
var part = dipSwitch.GetFieldValue(DipSwitch.PartKey);
if (part != null)
RemoveFields(part as DatItem, [], itemFieldNames);
}
///
/// Remove fields with given values
///
/// DipValue to remove fields from
private static void RemoveFields(DipValue dipValue, Dictionary> itemFieldNames)
{
var conditions = dipValue.GetFieldValue(Models.Metadata.DipValue.ConditionKey) ?? [];
foreach (Condition subCondition in conditions)
{
RemoveFields(subCondition, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Disk to remove fields from
private static void RemoveFields(Disk disk, Dictionary> itemFieldNames)
{
var diskArea = disk.GetFieldValue(Disk.DiskAreaKey);
if (diskArea != null)
RemoveFields(diskArea as DatItem, [], itemFieldNames);
var part = disk.GetFieldValue(Disk.PartKey);
if (part != null)
RemoveFields(part as DatItem, [], itemFieldNames);
}
///
/// Remove fields with given values
///
/// Input to remove fields from
private static void RemoveFields(Input input, Dictionary> itemFieldNames)
{
var controls = input.GetFieldValue(Models.Metadata.Input.ControlKey) ?? [];
foreach (Control subControl in controls)
{
RemoveFields(subControl, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Part to remove fields from
private static void RemoveFields(Part part, Dictionary> itemFieldNames)
{
var features = part.GetFieldValue(Models.Metadata.Part.FeatureKey) ?? [];
foreach (PartFeature subPartFeature in features)
{
RemoveFields(subPartFeature, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Port to remove fields from
private static void RemoveFields(Port port, Dictionary> itemFieldNames)
{
var analogs = port.GetFieldValue(Models.Metadata.Port.AnalogKey) ?? [];
foreach (Analog subAnalog in analogs)
{
RemoveFields(subAnalog, [], itemFieldNames);
}
}
///
/// Remove fields with given values
///
/// Rom to remove fields from
private static void RemoveFields(Rom rom, Dictionary> itemFieldNames)
{
var dataArea = rom.GetFieldValue(Rom.DataAreaKey);
if (dataArea != null)
RemoveFields(dataArea as DatItem, [], itemFieldNames);
var part = rom.GetFieldValue(Rom.PartKey);
if (part != null)
RemoveFields(part as DatItem, [], itemFieldNames);
}
///
/// Remove fields with given values
///
/// Slot to remove fields from
private static void RemoveFields(Slot slot, Dictionary> itemFieldNames)
{
var slotOptions = slot.GetFieldValue(Models.Metadata.Slot.SlotOptionKey) ?? [];
foreach (SlotOption subSlotOption in slotOptions)
{
RemoveFields(subSlotOption, [], itemFieldNames);
}
}
#endregion
}
}