using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.EntityFrameworkCore; using TournamentOrganizer.Models; namespace TournamentOrganizer.ViewModels; public partial class EventsViewModel : ViewModelBase { private readonly TournamentContext _context; [ObservableProperty] private ObservableCollection _events = []; [ObservableProperty] private EventDisplay? _selectedEvent; [ObservableProperty] private string _eventName = string.Empty; [ObservableProperty] private DateTime _eventStart = DateTime.Today; [ObservableProperty] private DateTime _eventEnd = DateTime.Today.AddDays(1); [ObservableProperty] private ObservableCollection _tournaments = []; [ObservableProperty] private TournamentDisplay? _selectedTournament; [ObservableProperty] private GameOption? _selectedGameToAdd; [ObservableProperty] private string _filterEventName = string.Empty; [ObservableProperty] private bool _isEditing; [ObservableProperty] private string _statusMessage = string.Empty; private readonly ObservableCollection _availableGames = []; private readonly ObservableCollection _availableGamesToAdd = []; public ObservableCollection AvailableGamesToAdd => _availableGamesToAdd; public EventsViewModel() { _context = new TournamentContext(); } partial void OnFilterEventNameChanged(string value) => ApplyFilters(); private async void ApplyFilters() { await LoadEvents(); } public async Task LoadEvents() { var games = await _context.Games.ToListAsync(); _availableGames.Clear(); _availableGamesToAdd.Clear(); foreach (var g in games) { var option = new GameOption(g); _availableGames.Add(option); _availableGamesToAdd.Add(option); } var allEvents = await _context.Events .Include(e => e.Tournaments) .ThenInclude(t => t.Game) .ToListAsync(); var filtered = allEvents.AsEnumerable(); if (!string.IsNullOrWhiteSpace(FilterEventName)) { var filter = FilterEventName.ToLower(); filtered = filtered.Where(e => e.Name.ToLower().Contains(filter)); } Events.Clear(); foreach (var evt in filtered) { Events.Add(new EventDisplay(evt)); } SelectedEvent = null; IsEditing = false; } [RelayCommand] private async Task RefreshEvents() { await LoadEvents(); } [RelayCommand] private void CreateNewEvent() { EventName = "New Event"; EventStart = DateTime.Today; EventEnd = DateTime.Today.AddDays(1); Tournaments.Clear(); IsEditing = true; SelectedEvent = null; SelectedGameToAdd = null; StatusMessage = "Creating new event"; } [RelayCommand] private async Task SaveEvent() { if (string.IsNullOrWhiteSpace(EventName)) { StatusMessage = "Event name is required"; return; } if (EventEnd <= EventStart) { StatusMessage = "End date must be after start date"; return; } Event? evt; if (SelectedEvent != null && SelectedEvent.Id > 0) { evt = await _context.Events .Include(e => e.Tournaments) .FirstOrDefaultAsync(e => e.Id == SelectedEvent.Id); if (evt == null) { StatusMessage = "Event not found"; return; } evt.Name = EventName; evt.Start = EventStart; evt.End = EventEnd; } else { evt = new Event { Name = EventName, Start = EventStart, End = EventEnd, Tournaments = [] }; _context.Events.Add(evt); } await _context.SaveChangesAsync(); StatusMessage = $"Event '{EventName}' saved successfully"; await LoadEvents(); } [RelayCommand] private async Task DeleteEvent() { if (SelectedEvent == null || SelectedEvent.Id == 0) { StatusMessage = "Select an event to delete"; return; } var evt = await _context.Events .Include(e => e.Tournaments) .FirstOrDefaultAsync(e => e.Id == SelectedEvent.Id); if (evt == null) { StatusMessage = "Event not found"; return; } _context.Events.Remove(evt); await _context.SaveChangesAsync(); StatusMessage = $"Event '{evt.Name}' deleted"; await LoadEvents(); } [RelayCommand] private async Task AddGameToEvent() { if (SelectedGameToAdd == null) { StatusMessage = "Select a game to add"; return; } if (SelectedEvent == null || SelectedEvent.Id == 0) { StatusMessage = "Save the event first before adding games"; return; } var evt = await _context.Events .Include(e => e.Tournaments) .FirstOrDefaultAsync(e => e.Id == SelectedEvent.Id); if (evt == null) { StatusMessage = "Event not found"; return; } if (evt.Tournaments.Any(t => t.GameId == SelectedGameToAdd.Game.Id)) { StatusMessage = "This game is already added to the event"; return; } var tournament = new Tournament { GameId = SelectedGameToAdd.Game.Id, EventId = evt.Id, Start = evt.Start, End = evt.End, S1RuleSet = SelectedGameToAdd.Game.S1RuleSet, S1Groups = SelectedGameToAdd.Game.S1Groups, S1GroupAdvances = SelectedGameToAdd.Game.S1GroupAdvances, S2RuleSet = SelectedGameToAdd.Game.S2RuleSet, Game = SelectedGameToAdd.Game, Event = evt }; evt.Tournaments.Add(tournament); await _context.SaveChangesAsync(); StatusMessage = $"Added '{SelectedGameToAdd.Game.Name}' to event"; await LoadEventDetails(); } [RelayCommand] private async Task RemoveGameFromEvent() { if (SelectedTournament == null) { StatusMessage = "Select a tournament to remove"; return; } if (SelectedEvent == null || SelectedEvent.Id == 0) { StatusMessage = "Select an event first"; return; } var tournament = await _context.Tournaments.FirstOrDefaultAsync(t => t.Id == SelectedTournament.Id); if (tournament == null) { StatusMessage = "Tournament not found"; return; } _context.Tournaments.Remove(tournament); await _context.SaveChangesAsync(); StatusMessage = $"Removed '{SelectedTournament.GameName}' from event"; await LoadEventDetails(); } private async Task LoadEventDetails() { var allEvents = await _context.Events .Include(e => e.Tournaments) .ThenInclude(t => t.Game) .ToListAsync(); var evt = allEvents.FirstOrDefault(e => e.Id == (SelectedEvent?.Id ?? 0)); if (evt == null) { Tournaments.Clear(); return; } Tournaments.Clear(); foreach (var t in evt.Tournaments) { Tournaments.Add(new TournamentDisplay(t)); } SelectedTournament = null; _availableGamesToAdd.Clear(); foreach (var g in _availableGames) { if (!Tournaments.Any(t => t.GameId == g.Game.Id)) { _availableGamesToAdd.Add(g); } } SelectedGameToAdd = null; } partial void OnSelectedEventChanged(EventDisplay? value) { if (value == null) { IsEditing = false; Tournaments.Clear(); return; } EventName = value.Name; EventStart = value.Start; EventEnd = value.End; IsEditing = true; _ = LoadEventDetails(); StatusMessage = $"Editing event '{value.Name}'"; } } public class EventDisplay { public int Id { get; set; } public string Name { get; set; } = string.Empty; public DateTime Start { get; set; } public DateTime End { get; set; } public List TournamentNames { get; set; } = []; public EventDisplay() { } public EventDisplay(Event evt) { Id = evt.Id; Name = evt.Name; Start = evt.Start; End = evt.End; if (evt.Tournaments != null) { TournamentNames = evt.Tournaments.Select(t => t.Game.Name).ToList(); } } } public class TournamentDisplay { public int Id { get; set; } public int GameId { get; set; } public string GameName { get; set; } = string.Empty; public RuleSet S1RuleSet { get; set; } public string S1RuleSetName => S1RuleSet.ToDisplayName(); public RuleSet? S2RuleSet { get; set; } public string? S2RuleSetName => S2RuleSet?.ToDisplayName(); public TournamentDisplay() { } public TournamentDisplay(Tournament tournament) { Id = tournament.Id; GameId = tournament.GameId; GameName = tournament.Game.Name; S1RuleSet = tournament.S1RuleSet; S2RuleSet = tournament.S2RuleSet; } } public class GameOption { public Game Game { get; set; } = null!; public string DisplayName { get; set; } = string.Empty; public GameOption() { } public GameOption(Game game) { Game = game; DisplayName = game.Name; } public override string ToString() => DisplayName; }