using System; using System.IO; using System.Text.Json; using System.Text.Json.Serialization; using GeViSetEditor.Core.Models; using GeViSetEditor.Core.Parsers; namespace GeViSetEditor.CLI.Commands { /// /// Export .set file to JSON format (action mappings + metadata) /// Binary data is preserved for round-trip conversion /// public static class ExportJsonCommand { public static void Execute(string inputPath, string outputJsonPath) { Console.WriteLine("=== Export to JSON ===\n"); if (!File.Exists(inputPath)) { Console.WriteLine($"ERROR: File not found: {inputPath}"); return; } try { // Parse with safe parser byte[] data = File.ReadAllBytes(inputPath); var parser = new SafeSetFileParser(); var setFile = parser.Parse(data); Console.WriteLine($"\nFile: {inputPath}"); Console.WriteLine($"Size: {setFile.FileSize:N0} bytes"); Console.WriteLine($"Header: '{setFile.Header}'"); Console.WriteLine($"Action Mappings: {setFile.ActionMappings.Count}"); // Create JSON-friendly export model var exportModel = new SetFileJsonExport { Version = "1.0", SourceFile = Path.GetFileName(inputPath), FileSize = setFile.FileSize, Header = setFile.Header, ExportDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), ActionMappings = setFile.ActionMappings.Select((m, index) => new ActionMappingJson { Id = index + 1, FileOffset = m.FileOffset, RulesMarkerOffset = m.RulesMarkerOffset, Actions = m.Actions.ToList(), TriggerConditions = m.TriggerConditions.ToDictionary(kv => kv.Key, kv => kv.Value) }).ToList() }; // Serialize to JSON var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }; string json = JsonSerializer.Serialize(exportModel, options); // Write to file File.WriteAllText(outputJsonPath, json); Console.WriteLine($"\n✓ JSON exported successfully!"); Console.WriteLine($"Output: {outputJsonPath}"); Console.WriteLine($"JSON size: {json.Length:N0} characters ({json.Length / 1024:N0} KB)"); // Show statistics Console.WriteLine($"\n=== Statistics ==="); Console.WriteLine($"Total mappings: {exportModel.ActionMappings.Count}"); Console.WriteLine($"Total actions: {exportModel.ActionMappings.Sum(m => m.Actions.Count)}"); var actionsPerMapping = exportModel.ActionMappings.GroupBy(m => m.Actions.Count); Console.WriteLine($"\nActions per mapping:"); foreach (var group in actionsPerMapping.OrderBy(g => g.Key)) { Console.WriteLine($" {group.Key} actions: {group.Count()} mappings"); } } catch (Exception ex) { Console.WriteLine($"\n✗ ERROR: {ex.Message}"); Console.WriteLine($"Stack trace:\n{ex.StackTrace}"); } } } /// /// JSON export model (without binary data) /// public class SetFileJsonExport { [JsonPropertyName("version")] public string Version { get; set; } [JsonPropertyName("sourceFile")] public string SourceFile { get; set; } [JsonPropertyName("exportDate")] public string ExportDate { get; set; } [JsonPropertyName("fileSize")] public int FileSize { get; set; } [JsonPropertyName("header")] public string Header { get; set; } [JsonPropertyName("actionMappings")] public List ActionMappings { get; set; } = new(); } public class ActionMappingJson { [JsonPropertyName("id")] public int Id { get; set; } [JsonPropertyName("fileOffset")] public int FileOffset { get; set; } [JsonPropertyName("rulesMarkerOffset")] public int RulesMarkerOffset { get; set; } [JsonPropertyName("actions")] public List Actions { get; set; } = new(); [JsonPropertyName("triggerConditions")] public Dictionary TriggerConditions { get; set; } = new(); } }