using RobotNet10.MapEditor.Shared.DTOs.Layout; using RobotNet10.MapEditor.Shared.DTOs.LayoutData; using RobotNet10.MapEditor.Shared.DTOs.Requests; using RobotNet10.MapEditor.Services.API; namespace RobotNet10.MapEditor.Services.State; /// /// State management for LayoutManager page /// public class LayoutManagerState { // ===== DATA ===== public List Layouts { get; set; } = new(); // ===== SELECTION ===== public LayoutDto? SelectedLayout { get; set; } public LayoutVersionDto? SelectedVersion { get; set; } public LayoutLevelDto? SelectedLevel { get; set; } // ===== PREVIEW DATA ===== public LayoutDataDto? PreviewData { get; set; } public byte[]? PreviewImage { get; set; } // ===== UI STATE ===== public bool IsLoading { get; set; } public bool IsLoadingPreview { get; set; } public string? SearchText { get; set; } // ===== EVENTS ===== public event Action? OnStateChanged; // ===== DEPENDENCIES ===== private readonly MapManagerApiService _apiService; public LayoutManagerState(MapManagerApiService apiService) { _apiService = apiService; } // ========================================== // PUBLIC METHODS // ========================================== /// /// Load all layouts with nested versions and levels /// public async Task LoadLayoutsAsync(string? searchText = null) { IsLoading = true; SearchText = searchText; NotifyStateChanged(); try { Layouts = await _apiService.SearchLayoutsAsync(searchText); } catch (Exception ex) { Console.WriteLine($"Error loading layouts: {ex.Message}"); Layouts = new(); } IsLoading = false; NotifyStateChanged(); } /// /// Select a level and load preview data /// public async Task SelectLevelAsync(LayoutLevelDto level) { SelectedLevel = level; // Find parent version and layout foreach (var layout in Layouts) { if (layout.Versions == null) continue; foreach (var version in layout.Versions) { if (version.Levels?.Any(l => l.Id == level.Id) == true) { SelectedLayout = layout; SelectedVersion = version; break; } } if (SelectedVersion != null) break; } await LoadPreviewAsync(level.Id); } /// /// Clear selection /// public void ClearSelection() { SelectedLayout = null; SelectedVersion = null; SelectedLevel = null; PreviewData = null; PreviewImage = null; NotifyStateChanged(); } /// /// Create new layout /// public async Task CreateLayoutAsync(CreateLayoutRequest request) { var layout = await _apiService.CreateLayoutAsync(request); await LoadLayoutsAsync(SearchText); // Reload return layout; } /// /// Delete layout /// public async Task DeleteLayoutAsync(Guid layoutId) { await _apiService.DeleteLayoutAsync(layoutId); await LoadLayoutsAsync(SearchText); // Reload // Clear selection if deleted if (SelectedLayout?.Id == layoutId) { ClearSelection(); } } /// /// Create new version /// public async Task CreateVersionAsync(Guid layoutId, CreateLayoutVersionRequest request) { var version = await _apiService.CreateVersionAsync(layoutId, request); await LoadLayoutsAsync(SearchText); // Reload return version; } /// /// Delete version /// public async Task DeleteVersionAsync(Guid versionId) { await _apiService.DeleteVersionAsync(versionId); await LoadLayoutsAsync(SearchText); // Reload // Clear selection if deleted if (SelectedVersion?.Id == versionId) { ClearSelection(); } } /// /// Create new level /// public async Task CreateLevelAsync(Guid versionId, CreateLayoutLevelRequest request) { var level = await _apiService.CreateLevelAsync(versionId, request); await LoadLayoutsAsync(SearchText); // Reload return level; } /// /// Delete level /// public async Task DeleteLevelAsync(Guid levelId) { await _apiService.DeleteLevelAsync(levelId); await LoadLayoutsAsync(SearchText); // Reload // Clear selection if deleted if (SelectedLevel?.Id == levelId) { ClearSelection(); } } /// /// Activate layout /// public async Task ActivateLayoutAsync(Guid layoutId) { await _apiService.ActivateLayoutAsync(layoutId); await LoadLayoutsAsync(SearchText); // Reload to get updated IsActive status } /// /// Deactivate layout /// public async Task DeactivateLayoutAsync(Guid layoutId) { await _apiService.DeactivateLayoutAsync(layoutId); await LoadLayoutsAsync(SearchText); // Reload } // ========================================== // PRIVATE METHODS // ========================================== /// /// Load preview data (nodes, edges, image) /// private async Task LoadPreviewAsync(Guid levelId) { IsLoadingPreview = true; NotifyStateChanged(); try { // Load layout data PreviewData = await _apiService.GetLayoutDataAsync(levelId); // Load background image try { PreviewImage = await _apiService.GetLayoutImageAsync(levelId); } catch { PreviewImage = null; // Image might not exist yet } } catch (Exception ex) { Console.WriteLine($"Error loading preview: {ex.Message}"); PreviewData = null; PreviewImage = null; } IsLoadingPreview = false; NotifyStateChanged(); } private void NotifyStateChanged() => OnStateChanged?.Invoke(); }