using System; using System.Collections.Generic; using System.Linq; using CommunityToolkit.Mvvm.ComponentModel; using Wino.Core.Domain.Interfaces; namespace Wino.Mail.ViewModels.Data; /// /// Thread mail item (multiple IMailItem) view model representation. /// public partial class ThreadMailItemViewModel : ObservableRecipient, IDisposable, IMailListItem { private readonly string _threadId; private readonly List _threadEmails = []; private bool _disposed; [ObservableProperty] [NotifyPropertyChangedRecipients] public partial bool IsThreadExpanded { get; set; } [ObservableProperty] public partial bool IsSelected { get; set; } /// /// Gets the number of emails in this thread /// public int EmailCount => _threadEmails.Count; /// /// Gets the latest email's subject for display /// public string Subject => _threadEmails .OrderByDescending(e => e.MailCopy?.CreationDate) .FirstOrDefault()?.MailCopy?.Subject; /// /// Gets the latest email's sender name for display /// public string FromName => _threadEmails .OrderByDescending(e => e.MailCopy?.CreationDate) .FirstOrDefault()?.MailCopy?.SenderContact.Name; /// /// Gets the latest email's creation date for sorting /// public DateTime CreationDate => _threadEmails .OrderByDescending(e => e.MailCopy?.CreationDate) .FirstOrDefault()?.MailCopy?.CreationDate ?? DateTime.MinValue; /// /// Gets all emails in this thread (read-only) /// public IReadOnlyList ThreadEmails => _threadEmails.AsReadOnly(); public MailItemViewModel LatestMailViewModel => _threadEmails.OrderByDescending(e => e.MailCopy?.CreationDate).FirstOrDefault()!; public ThreadMailItemViewModel(string threadId) { _threadId = threadId; } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _threadEmails.Clear(); } _disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void NotifyPropertyChanges() { OnPropertyChanged(nameof(Subject)); OnPropertyChanged(nameof(FromName)); OnPropertyChanged(nameof(CreationDate)); OnPropertyChanged(nameof(LatestMailViewModel)); } /// /// Adds an email to this thread /// public void AddEmail(MailItemViewModel email) { if (email.MailCopy.ThreadId != _threadId) throw new ArgumentException($"Email ThreadId '{email.MailCopy.ThreadId}' does not match expander ThreadId '{_threadId}'"); _threadEmails.Add(email); NotifyPropertyChanges(); } /// /// Removes an email from this thread /// public void RemoveEmail(MailItemViewModel email) { if (_threadEmails.Remove(email)) { NotifyPropertyChanges(); } } /// /// Checks if this thread contains an email with the specified unique ID /// public bool HasUniqueId(Guid uniqueId) => _threadEmails.Any(email => email.MailCopy.UniqueId == uniqueId); public IEnumerable GetContainingIds() => ThreadEmails.Select(a => a.MailCopy.UniqueId); public IEnumerable GetSelectedMailItems() { if (IsSelected) { // If the thread itself is selected, return all emails in the thread return ThreadEmails; } else { // Otherwise, return only individually selected emails within the thread return ThreadEmails.Where(e => e.IsSelected); } } }