#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using Newtonsoft.Json;
using SabreTools.DatItems;
namespace SabreTools.DatFiles
{
///
/// Item dictionary with statistics, bucketing, and sorting
///
[JsonObject("items"), XmlRoot("items")]
public class ItemDictionaryDB
{
#region Private instance variables
///
/// Internal dictionary for all items
///
[JsonIgnore, XmlIgnore]
#if NET40_OR_GREATER || NETCOREAPP
private readonly ConcurrentDictionary _items = new ConcurrentDictionary();
#else
private readonly Dictionary _items = [];
#endif
///
/// Current highest available item index
///
private long _itemIndex = 0;
///
/// Internal dictionary for all machines
///
[JsonIgnore, XmlIgnore]
#if NET40_OR_GREATER || NETCOREAPP
private readonly ConcurrentDictionary _machines = new ConcurrentDictionary();
#else
private readonly Dictionary _machines = [];
#endif
///
/// Current highest available machine index
///
private long _machineIndex = 0;
///
/// Internal dictionary for item to machine mappings
///
[JsonIgnore, XmlIgnore]
#if NET40_OR_GREATER || NETCOREAPP
private readonly ConcurrentDictionary _itemToMachineMapping = new ConcurrentDictionary();
#else
private readonly Dictionary _itemToMachineMapping = [];
#endif
// TODO: Add another dictionary of string => ConcurrentList representing a bucketed key to a set of item IDs
#endregion
#region Fields
///
/// DAT statistics
///
[JsonIgnore, XmlIgnore]
public DatStatistics DatStatistics { get; } = new DatStatistics();
#endregion
#region Accessors
///
/// Add an item, returning the insert index
///
public long AddItem(DatItem item)
{
_items[_itemIndex++] = item;
DatStatistics.AddItemStatistics(item);
return _itemIndex - 1;
}
///
/// Add a machine, returning the insert index
///
public long AddMachine(Machine machine)
{
_machines[_machineIndex++] = machine;
return _machineIndex - 1;
}
///
/// Get an item based on the index
///
public DatItem? GetItemByIndex(long index)
{
if (!_items.ContainsKey(index))
return null;
return _items[index];
}
///
/// Get a machine based on the index
///
public Machine? GetMachineByIndex(long index)
{
if (!_machines.ContainsKey(index))
return null;
return _machines[index];
}
///
/// Get the machine associated with an item index
///
public Machine? GetMachineForItemByIndex(long itemIndex)
{
if (!_itemToMachineMapping.ContainsKey(itemIndex))
return null;
long machineIndex = _itemToMachineMapping[itemIndex];
if (!_machines.ContainsKey(machineIndex))
return null;
return _machines[machineIndex];
}
///
/// Get the items associated with a machine index
///
public DatItem[]? GetDatItemsForMachineByIndex(long machineIndex)
{
var itemIds = _itemToMachineMapping
.Where(mapping => mapping.Value == machineIndex)
.Select(mapping => mapping.Key);
var datItems = new List();
foreach (long itemId in itemIds)
{
if (_items.ContainsKey(itemId))
datItems.Add(_items[itemId]);
}
return datItems.ToArray();
}
///
/// Remove an item, returning if it could be removed
///
public bool RemoveItem(long itemIndex)
{
if (!_items.ContainsKey(itemIndex))
return false;
#if NET40_OR_GREATER || NETCOREAPP
_items.TryRemove(itemIndex, out _);
#else
_items.Remove(itemIndex);
#endif
if (_itemToMachineMapping.ContainsKey(itemIndex))
#if NET40_OR_GREATER || NETCOREAPP
_itemToMachineMapping.TryRemove(itemIndex, out _);
#else
_itemToMachineMapping.Remove(itemIndex);
#endif
return true;
}
///
/// Remove a machine, returning if it could be removed
///
public bool RemoveMachine(long machineIndex)
{
if (!_machines.ContainsKey(machineIndex))
return false;
#if NET40_OR_GREATER || NETCOREAPP
_machines.TryRemove(machineIndex, out _);
#else
_machines.Remove(machineIndex);
#endif
var itemIds = _itemToMachineMapping
.Where(mapping => mapping.Value == machineIndex)
.Select(mapping => mapping.Key);
foreach (long itemId in itemIds)
{
#if NET40_OR_GREATER || NETCOREAPP
_itemToMachineMapping.TryRemove(itemId, out _);
#else
_itemToMachineMapping.Remove(itemId);
#endif
}
return true;
}
#endregion
}
}