using System; using System.Xml.Serialization; using Newtonsoft.Json; using SabreTools.Data.Extensions; using SabreTools.Metadata.Filter; using SabreTools.Text.Extensions; namespace SabreTools.Metadata.DatItems { /// /// Represents the information specific to a set/game/machine /// [JsonObject("machine"), XmlRoot("machine")] public sealed class Machine : ModelBackedItem, ICloneable, IEquatable { #region Constructors public Machine() { _internal = []; } public Machine(Data.Models.Metadata.Machine machine) { _internal = machine.Clone() as Data.Models.Metadata.Machine ?? []; // Remove all inverted fields Remove(Data.Models.Metadata.Machine.AdjusterKey); Remove(Data.Models.Metadata.Machine.ArchiveKey); Remove(Data.Models.Metadata.Machine.BiosSetKey); Remove(Data.Models.Metadata.Machine.ChipKey); Remove(Data.Models.Metadata.Machine.ConfigurationKey); Remove(Data.Models.Metadata.Machine.DeviceKey); Remove(Data.Models.Metadata.Machine.DeviceRefKey); Remove(Data.Models.Metadata.Machine.DipSwitchKey); Remove(Data.Models.Metadata.Machine.DiskKey); Remove(Data.Models.Metadata.Machine.DisplayKey); Remove(Data.Models.Metadata.Machine.DriverKey); Remove(Data.Models.Metadata.Machine.DumpKey); Remove(Data.Models.Metadata.Machine.FeatureKey); Remove(Data.Models.Metadata.Machine.InfoKey); Remove(Data.Models.Metadata.Machine.InputKey); Remove(Data.Models.Metadata.Machine.MediaKey); Remove(Data.Models.Metadata.Machine.PartKey); Remove(Data.Models.Metadata.Machine.PortKey); Remove(Data.Models.Metadata.Machine.RamOptionKey); Remove(Data.Models.Metadata.Machine.ReleaseKey); Remove(Data.Models.Metadata.Machine.RomKey); Remove(Data.Models.Metadata.Machine.SampleKey); Remove(Data.Models.Metadata.Machine.SharedFeatKey); Remove(Data.Models.Metadata.Machine.SlotKey); Remove(Data.Models.Metadata.Machine.SoftwareListKey); Remove(Data.Models.Metadata.Machine.SoundKey); Remove(Data.Models.Metadata.Machine.TruripKey); Remove(Data.Models.Metadata.Machine.VideoKey); // Process flag values string? im1Crc = ReadString(Data.Models.Metadata.Machine.Im1CRCKey); if (im1Crc is not null) Write(Data.Models.Metadata.Machine.Im1CRCKey, TextHelper.NormalizeCRC32(im1Crc)); string? im2Crc = ReadString(Data.Models.Metadata.Machine.Im2CRCKey); if (im2Crc is not null) Write(Data.Models.Metadata.Machine.Im2CRCKey, TextHelper.NormalizeCRC32(im2Crc)); bool? isBios = ReadBool(Data.Models.Metadata.Machine.IsBiosKey); if (isBios is not null) Write(Data.Models.Metadata.Machine.IsBiosKey, isBios.FromYesNo()); bool? isDevice = ReadBool(Data.Models.Metadata.Machine.IsDeviceKey); if (isDevice is not null) Write(Data.Models.Metadata.Machine.IsDeviceKey, isDevice.FromYesNo()); bool? isMechanical = ReadBool(Data.Models.Metadata.Machine.IsMechanicalKey); if (isMechanical is not null) Write(Data.Models.Metadata.Machine.IsMechanicalKey, isMechanical.FromYesNo()); string? supported = ReadString(Data.Models.Metadata.Machine.SupportedKey); if (supported is not null) Write(Data.Models.Metadata.Machine.SupportedKey, supported.AsSupported()?.AsStringValue()); // Handle Trurip object, if it exists var truripItem = machine.Read(Data.Models.Metadata.Machine.TruripKey); if (truripItem is not null) Write(Data.Models.Metadata.Machine.TruripKey, new Trurip(truripItem)); } #endregion #region Accessors /// /// Gets the name to use for a Machine /// /// Name if available, null otherwise public string? GetName() => _internal.GetName(); /// /// Sets the name to use for a Machine /// /// Name to set for the item public void SetName(string? name) => _internal.SetName(name); #endregion #region Cloning methods /// /// Create a clone of the current machine /// /// New machine with the same values as the current one public object Clone() { return new Machine() { _internal = _internal.Clone() as Data.Models.Metadata.Machine ?? [], }; } /// /// Get a clone of the current internal model /// public Data.Models.Metadata.Machine GetInternalClone() => (_internal.Clone() as Data.Models.Metadata.Machine)!; #endregion #region Comparision Methods /// public override bool Equals(ModelBackedItem? other) { // If other is null if (other is null) return false; // If the type is mismatched if (other is not Machine otherItem) return false; // Compare internal models return _internal.EqualTo(otherItem._internal); } /// public override bool Equals(ModelBackedItem? other) { // If other is null if (other is null) return false; // If the type is mismatched if (other is not Machine otherItem) return false; // Compare internal models return _internal.EqualTo(otherItem._internal); } /// public bool Equals(Machine? other) { // If other is null if (other is null) return false; // Compare internal models return _internal.EqualTo(other._internal); } #endregion #region Manipulation /// /// Runs a filter and determines if it passes or not /// /// Filter runner to use for checking /// True if the Machine passes the filter, false otherwise public bool PassesFilter(FilterRunner filterRunner) => filterRunner.Run(_internal); #endregion } }