using System.IO; using System.Text; using EonaCat.FirstLight.SaveTransfer.VdfGenerator; using EonaCat.FirstLight.SaveTransfer.VdfGenerator.KeyValue; using EonaCat.FirstLight.SaveTransfer.VdfGenerator.KeyValue.Models; namespace EonaCat.FirstLight.SaveTransfer.VdfGenerator.Models; public class RemoteCacheVdfFile(int appId) { public const string FileName = "remotecache"; public const string FileExtension = ".vdf"; public int AppId { get; set; } = appId; public int ChangeNumber { get; set; } public int OsType { get; set; } public List CachedFiles { get; set; } = []; /// /// Retrieves the application identifier from the specified file path. /// /// The file system path from which to extract the application identifier. Must contain a parent directory whose name is a valid integer. /// The application identifier parsed from the parent directory name of the specified path. /// Thrown if the parent directory name of the specified path is not a valid integer. private static int GetAppIdFromPath(string path) { var parent = Path.GetFileName(Path.GetDirectoryName(path)); return int.TryParse(parent, out var result) ? result : throw new InvalidOperationException("Invalid AppId in path"); } /// /// Initializes a new instance of the class using the specified remote folder path and loads metadata for all files within the folder and its subdirectories. /// /// The full path to the remote folder containing the files to be cached. Must not be null or empty. public RemoteCacheVdfFile(string remoteFolderPath) : this(GetAppIdFromPath(remoteFolderPath)) { var files = Directory.GetFiles(remoteFolderPath, "*", SearchOption.AllDirectories); foreach (var file in files) CachedFiles.Add(new CachedFileMetadata(file, remoteFolderPath)); } /// /// Initializes a new instance of the class based on the provided key–value (KV) group, copying the relevant metadata. /// /// The KV group from which metadata and the list of cached files are read. Must not be null. public RemoteCacheVdfFile(KeyValueGroup group) : this(group.Key) { foreach (var node in group.Nodes) { // If the node is a KvGroup, we create a new CachedFileMetadata object using the group and add it to the CachedFiles list. if (node is KeyValueGroup fileGroup) { CachedFiles.Add(new CachedFileMetadata(fileGroup)); continue; } // If the node is not a KvGroup, we attempt to cast it to a KvPair to extract the key and value for the properties of RemoteCacheVdfFile. var kvPair = node as KeyValue.Models.KeyValuePair; switch (kvPair?.Key) { case "ChangeNumber": ChangeNumber = NumberParser.ParseInt(kvPair.Value); break; case "OSType": OsType = NumberParser.ParseInt(kvPair.Value); break; } } } /// /// Exports the current object and its cached files as a key-value group representation. /// /// A KvGroup containing the key-value pairs for the current object and its cached files. public KeyValueGroup ExportAsKvGroup() { var kvGroup = new KeyValueGroup(AppId.ToString()) .Add("ChangeNumber", ChangeNumber.ToString()) .Add("OSType", OsType.ToString()); foreach (var cachedFile in CachedFiles) kvGroup.Add(cachedFile.ExportAsKvGroup()); return kvGroup; } /// /// Exports the current data to a file in the specified destination folder. /// /// The path to the folder where the exported file will be created. Must be a valid, writable directory. public void ExportAsFile(string destinationFolder) { var kv = ExportAsKvGroup(); var serialized = KeyValueSerializer.Serialize(kv); var outputFilePath = Path.Combine(destinationFolder, $"{FileName}{FileExtension}"); File.WriteAllText(outputFilePath, serialized, new UTF8Encoding()); } }