2025-12-26 20:46:48 +01:00
using System ;
using System.Collections.Generic ;
using System.Collections.ObjectModel ;
using System.Linq ;
2025-12-30 10:36:27 +01:00
using CommunityToolkit.Mvvm.Collections ;
2025-12-26 20:46:48 +01:00
using CommunityToolkit.Mvvm.ComponentModel ;
using Wino.Calendar.ViewModels.Data ;
using Wino.Calendar.ViewModels.Interfaces ;
2025-12-30 10:02:24 +01:00
using Wino.Core.Domain.Entities.Shared ;
2025-12-26 20:46:48 +01:00
namespace Wino.Mail.WinUI.Services ;
/// <summary>
/// Encapsulated state manager for collectively managing the state of account calendars.
/// Callers must react to the events to update their state only from this service.
/// </summary>
public partial class AccountCalendarStateService : ObservableObject , IAccountCalendarStateService
{
2025-12-30 10:02:24 +01:00
public event EventHandler < GroupedAccountCalendarViewModel > ? CollectiveAccountGroupSelectionStateChanged ;
public event EventHandler < AccountCalendarViewModel > ? AccountCalendarSelectionStateChanged ;
private readonly ObservableCollection < GroupedAccountCalendarViewModel > _internalGroupedAccountCalendars ;
2025-12-30 10:36:27 +01:00
private readonly ObservableGroupedCollection < MailAccount , AccountCalendarViewModel > _internalGroupedCalendars ;
2025-12-26 20:46:48 +01:00
[ObservableProperty]
public partial ReadOnlyObservableCollection < GroupedAccountCalendarViewModel > GroupedAccountCalendars { get ; set ; }
2025-12-30 10:36:27 +01:00
[ObservableProperty]
public partial ReadOnlyObservableGroupedCollection < MailAccount , AccountCalendarViewModel > GroupedCalendars { get ; set ; }
2025-12-26 20:46:48 +01:00
public IEnumerable < AccountCalendarViewModel > ActiveCalendars
{
get
{
2025-12-30 10:02:24 +01:00
return _internalGroupedAccountCalendars
. SelectMany ( a = > a . AccountCalendars )
. Where ( b = > b . IsChecked ) ;
2025-12-26 20:46:48 +01:00
}
}
2025-12-30 10:02:24 +01:00
public IEnumerable < AccountCalendarViewModel > AllCalendars
{
get
{
return _internalGroupedAccountCalendars
. SelectMany ( a = > a . AccountCalendars ) ;
}
}
2025-12-26 20:46:48 +01:00
public AccountCalendarStateService ( )
{
2025-12-30 10:02:24 +01:00
_internalGroupedAccountCalendars = new ObservableCollection < GroupedAccountCalendarViewModel > ( ) ;
2025-12-26 20:46:48 +01:00
GroupedAccountCalendars = new ReadOnlyObservableCollection < GroupedAccountCalendarViewModel > ( _internalGroupedAccountCalendars ) ;
2025-12-30 10:36:27 +01:00
_internalGroupedCalendars = new ObservableGroupedCollection < MailAccount , AccountCalendarViewModel > ( ) ;
GroupedCalendars = new ReadOnlyObservableGroupedCollection < MailAccount , AccountCalendarViewModel > ( _internalGroupedCalendars ) ;
2025-12-26 20:46:48 +01:00
}
2025-12-30 10:02:24 +01:00
private void SingleGroupCalendarCollectiveStateChanged ( object? sender , EventArgs e )
= > CollectiveAccountGroupSelectionStateChanged ? . Invoke ( this , sender as GroupedAccountCalendarViewModel ? ? throw new InvalidOperationException ( "Sender must be GroupedAccountCalendarViewModel" ) ) ;
2025-12-26 20:46:48 +01:00
2025-12-30 10:02:24 +01:00
private void SingleCalendarSelectionStateChanged ( object? sender , AccountCalendarViewModel e )
2025-12-26 20:46:48 +01:00
= > AccountCalendarSelectionStateChanged ? . Invoke ( this , e ) ;
public void AddGroupedAccountCalendar ( GroupedAccountCalendarViewModel groupedAccountCalendar )
{
groupedAccountCalendar . CalendarSelectionStateChanged + = SingleCalendarSelectionStateChanged ;
groupedAccountCalendar . CollectiveSelectionStateChanged + = SingleGroupCalendarCollectiveStateChanged ;
_internalGroupedAccountCalendars . Add ( groupedAccountCalendar ) ;
2025-12-30 10:36:27 +01:00
// Maintain the grouped calendars collection
var group = _internalGroupedCalendars . FirstOrDefault < ObservableGroup < MailAccount , AccountCalendarViewModel > > ( g = > g . Key . Id = = groupedAccountCalendar . Account . Id ) ;
if ( group = = null )
{
_internalGroupedCalendars . Add ( new ObservableGroup < MailAccount , AccountCalendarViewModel > ( groupedAccountCalendar . Account , groupedAccountCalendar . AccountCalendars ) ) ;
}
else
{
foreach ( var calendar in groupedAccountCalendar . AccountCalendars )
{
group . Add ( calendar ) ;
}
}
2025-12-26 20:46:48 +01:00
}
public void RemoveGroupedAccountCalendar ( GroupedAccountCalendarViewModel groupedAccountCalendar )
{
groupedAccountCalendar . CalendarSelectionStateChanged - = SingleCalendarSelectionStateChanged ;
groupedAccountCalendar . CollectiveSelectionStateChanged - = SingleGroupCalendarCollectiveStateChanged ;
_internalGroupedAccountCalendars . Remove ( groupedAccountCalendar ) ;
2025-12-30 10:36:27 +01:00
// Maintain the grouped calendars collection
var group = _internalGroupedCalendars . FirstOrDefault < ObservableGroup < MailAccount , AccountCalendarViewModel > > ( g = > g . Key . Id = = groupedAccountCalendar . Account . Id ) ;
if ( group ! = null )
{
foreach ( var calendar in groupedAccountCalendar . AccountCalendars . ToList ( ) )
{
group . Remove ( calendar ) ;
}
if ( group . Count = = 0 )
{
_internalGroupedCalendars . Remove ( group ) ;
}
}
2025-12-26 20:46:48 +01:00
}
2025-12-30 10:02:24 +01:00
public void ClearGroupedAccountCalendars ( )
2025-12-26 20:46:48 +01:00
{
2025-12-27 19:16:24 +01:00
while ( _internalGroupedAccountCalendars . Any ( ) )
2025-12-26 20:46:48 +01:00
{
2025-12-27 19:16:24 +01:00
RemoveGroupedAccountCalendar ( _internalGroupedAccountCalendars [ 0 ] ) ;
2025-12-26 20:46:48 +01:00
}
}
public void AddAccountCalendar ( AccountCalendarViewModel accountCalendar )
{
// Find the group that this calendar belongs to.
var group = _internalGroupedAccountCalendars . FirstOrDefault ( g = > g . Account . Id = = accountCalendar . Account . Id ) ;
if ( group = = null )
{
// If the group doesn't exist, create it.
group = new GroupedAccountCalendarViewModel ( accountCalendar . Account , new [ ] { accountCalendar } ) ;
AddGroupedAccountCalendar ( group ) ;
}
else
{
group . AccountCalendars . Add ( accountCalendar ) ;
2025-12-30 10:36:27 +01:00
// Maintain the grouped calendars collection
var calendarGroup = _internalGroupedCalendars . FirstOrDefault < ObservableGroup < MailAccount , AccountCalendarViewModel > > ( g = > g . Key . Id = = accountCalendar . Account . Id ) ;
if ( calendarGroup = = null )
{
_internalGroupedCalendars . Add ( new ObservableGroup < MailAccount , AccountCalendarViewModel > ( accountCalendar . Account , new [ ] { accountCalendar } ) ) ;
}
else
{
calendarGroup . Add ( accountCalendar ) ;
}
2025-12-26 20:46:48 +01:00
}
}
public void RemoveAccountCalendar ( AccountCalendarViewModel accountCalendar )
{
var group = _internalGroupedAccountCalendars . FirstOrDefault ( g = > g . Account . Id = = accountCalendar . Account . Id ) ;
// We don't expect but just in case.
if ( group = = null ) return ;
group . AccountCalendars . Remove ( accountCalendar ) ;
2025-12-30 10:36:27 +01:00
// Maintain the grouped calendars collection
var calendarGroup = _internalGroupedCalendars . FirstOrDefault < ObservableGroup < MailAccount , AccountCalendarViewModel > > ( g = > g . Key . Id = = accountCalendar . Account . Id ) ;
if ( calendarGroup ! = null )
{
calendarGroup . Remove ( accountCalendar ) ;
if ( calendarGroup . Count = = 0 )
{
_internalGroupedCalendars . Remove ( calendarGroup ) ;
}
}
2025-12-26 20:46:48 +01:00
if ( group . AccountCalendars . Count = = 0 )
{
RemoveGroupedAccountCalendar ( group ) ;
}
}
}