using System.Collections.Generic; using SabreTools.Core.Tools; using SabreTools.DatItems; using SabreTools.DatItems.Formats; using SabreTools.IO.Logging; namespace SabreTools.DatFiles { /// /// Helper methods for updating and converting DatFiles /// public static class DatFileTool { #region Logging /// /// Logging object /// private static readonly Logger _staticLogger = new(); #endregion #region Sorting and Merging /// /// Merge an arbitrary set of DatItems based on the supplied information /// /// List of DatItem objects representing the items to be merged /// A List of DatItem objects representing the merged items public static List Merge(List? items) { // Check for null or blank inputs first if (items == null || items.Count == 0) return []; // Create output list List output = []; // Then deduplicate them by checking to see if data matches previous saved roms int nodumpCount = 0; foreach (DatItem datItem in items) { // If we don't have a Disk, File, Media, or Rom, we skip checking for duplicates if (datItem is not Disk && datItem is not DatItems.Formats.File && datItem is not Media && datItem is not Rom) continue; // If it's a nodump, add and skip if (datItem is Rom rom && rom.GetStringFieldValue(Models.Metadata.Rom.StatusKey).AsEnumValue() == ItemStatus.Nodump) { output.Add(datItem); nodumpCount++; continue; } else if (datItem is Disk disk && disk.GetStringFieldValue(Models.Metadata.Disk.StatusKey).AsEnumValue() == ItemStatus.Nodump) { output.Add(datItem); nodumpCount++; continue; } // If it's the first non-nodump item in the list, don't touch it if (output.Count == nodumpCount) { output.Add(datItem); continue; } // Find the index of the first duplicate, if one exists int pos = output.FindIndex(lastItem => datItem.GetDuplicateStatus(lastItem) != 0x00); if (pos < 0) { output.Add(datItem); continue; } // Get the duplicate item DatItem savedItem = output[pos]; DupeType dupetype = datItem.GetDuplicateStatus(savedItem); // Disks, File, Media, and Roms have more information to fill if (datItem is Disk diskItem && savedItem is Disk savedDisk) savedDisk.FillMissingInformation(diskItem); else if (datItem is DatItems.Formats.File fileItem && savedItem is DatItems.Formats.File savedFile) savedFile.FillMissingInformation(fileItem); else if (datItem is Media mediaItem && savedItem is Media savedMedia) savedMedia.FillMissingInformation(mediaItem); else if (datItem is Rom romItem && savedItem is Rom savedRom) savedRom.FillMissingInformation(romItem); // Set the duplicate type on the saved item savedItem.SetFieldValue(DatItem.DupeTypeKey, dupetype); // Get the sources associated with the items var savedSource = savedItem.GetFieldValue(DatItem.SourceKey); var itemSource = datItem.GetFieldValue(DatItem.SourceKey); // Get the machines associated with the items var savedMachine = savedItem.GetFieldValue(DatItem.MachineKey); var itemMachine = datItem.GetFieldValue(DatItem.MachineKey); // If the current source has a lower ID than the saved, use the saved source if (itemSource?.Index < savedSource?.Index) { datItem.SetFieldValue(DatItem.SourceKey, savedSource.Clone() as Source); savedItem.CopyMachineInformation(datItem); savedItem.SetName(datItem.GetName()); } // If the saved machine is a child of the current machine, use the current machine instead if (savedMachine?.GetStringFieldValue(Models.Metadata.Machine.CloneOfKey) == itemMachine?.GetStringFieldValue(Models.Metadata.Machine.NameKey) || savedMachine?.GetStringFieldValue(Models.Metadata.Machine.RomOfKey) == itemMachine?.GetStringFieldValue(Models.Metadata.Machine.NameKey)) { savedItem.CopyMachineInformation(datItem); savedItem.SetName(datItem.GetName()); } // Replace the original item in the list output.RemoveAt(pos); output.Insert(pos, savedItem); } // Then return the result return output; } #endregion } }