243 lines
6.7 KiB
C#
243 lines
6.7 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// State management for LayoutManager page
|
|
/// </summary>
|
|
public class LayoutManagerState
|
|
{
|
|
// ===== DATA =====
|
|
public List<LayoutDto> 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
|
|
// ==========================================
|
|
|
|
/// <summary>
|
|
/// Load all layouts with nested versions and levels
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Select a level and load preview data
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear selection
|
|
/// </summary>
|
|
public void ClearSelection()
|
|
{
|
|
SelectedLayout = null;
|
|
SelectedVersion = null;
|
|
SelectedLevel = null;
|
|
PreviewData = null;
|
|
PreviewImage = null;
|
|
NotifyStateChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new layout
|
|
/// </summary>
|
|
public async Task<LayoutDto> CreateLayoutAsync(CreateLayoutRequest request)
|
|
{
|
|
var layout = await _apiService.CreateLayoutAsync(request);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
return layout;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete layout
|
|
/// </summary>
|
|
public async Task DeleteLayoutAsync(Guid layoutId)
|
|
{
|
|
await _apiService.DeleteLayoutAsync(layoutId);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
|
|
// Clear selection if deleted
|
|
if (SelectedLayout?.Id == layoutId)
|
|
{
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new version
|
|
/// </summary>
|
|
public async Task<LayoutVersionDto> CreateVersionAsync(Guid layoutId, CreateLayoutVersionRequest request)
|
|
{
|
|
var version = await _apiService.CreateVersionAsync(layoutId, request);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
return version;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete version
|
|
/// </summary>
|
|
public async Task DeleteVersionAsync(Guid versionId)
|
|
{
|
|
await _apiService.DeleteVersionAsync(versionId);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
|
|
// Clear selection if deleted
|
|
if (SelectedVersion?.Id == versionId)
|
|
{
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new level
|
|
/// </summary>
|
|
public async Task<LayoutLevelDto> CreateLevelAsync(Guid versionId, CreateLayoutLevelRequest request)
|
|
{
|
|
var level = await _apiService.CreateLevelAsync(versionId, request);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
return level;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete level
|
|
/// </summary>
|
|
public async Task DeleteLevelAsync(Guid levelId)
|
|
{
|
|
await _apiService.DeleteLevelAsync(levelId);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
|
|
// Clear selection if deleted
|
|
if (SelectedLevel?.Id == levelId)
|
|
{
|
|
ClearSelection();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Activate layout
|
|
/// </summary>
|
|
public async Task ActivateLayoutAsync(Guid layoutId)
|
|
{
|
|
await _apiService.ActivateLayoutAsync(layoutId);
|
|
await LoadLayoutsAsync(SearchText); // Reload to get updated IsActive status
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deactivate layout
|
|
/// </summary>
|
|
public async Task DeactivateLayoutAsync(Guid layoutId)
|
|
{
|
|
await _apiService.DeactivateLayoutAsync(layoutId);
|
|
await LoadLayoutsAsync(SearchText); // Reload
|
|
}
|
|
|
|
// ==========================================
|
|
// PRIVATE METHODS
|
|
// ==========================================
|
|
|
|
/// <summary>
|
|
/// Load preview data (nodes, edges, image)
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|