using System;
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Diagnostics;
using OwlCore.AbstractUI.Models;
using StrixMusic.Sdk.AppModels;
using StrixMusic.Sdk.Services;
using Windows.UI.Xaml;
namespace StrixMusic.Sdk.WinUI.Services.NotificationService
{
///
public sealed class NotificationService : INotificationService
{
private readonly List _pendingNotifications;
private readonly List _activeNotifications;
///
public event EventHandler? NotificationRaised;
///
public event EventHandler? NotificationDismissed;
///
/// Raised when the notification margins are requested to be changed.
///
public event EventHandler? NotificationMarginChanged;
///
/// Raised when the notification alignment is requested to be changed.
///
public event EventHandler<(HorizontalAlignment, VerticalAlignment)>? NotificationAlignmentChanged;
///
/// Initializes a new instance of the class.
///
public NotificationService()
{
_pendingNotifications = new List();
_activeNotifications = new List();
}
///
event EventHandler? INotificationService.NotificationRaised
{
add => NotificationRaised += value;
remove => NotificationRaised -= value;
}
///
event EventHandler? INotificationService.NotificationDismissed
{
add => NotificationDismissed += value;
remove => NotificationDismissed -= value;
}
///
public int MaxActiveNotifications { get; set; } = 3;
///
public Notification RaiseNotification(string title, string message)
{
var id = Guid.NewGuid().ToString();
var elementGroup = new AbstractUICollection(id)
{
Title = title,
Subtitle = message,
};
return RaiseNotification(elementGroup);
}
///
public Notification RaiseNotification(AbstractUICollection elementGroup)
{
var notification = new Notification(elementGroup);
notification.Dismissed += Notification_Dismissed;
_pendingNotifications.Add(notification);
FireIfReady();
return notification;
}
private void Notification_Dismissed(object sender, EventArgs e)
{
if (sender is Notification notification)
{
var index = _activeNotifications.FindIndex(x => ReferenceEquals(x, notification));
if (index == -1)
return;
DismissNotificationInternal(index);
}
}
///
/// Request that the notification margin be changed.
///
/// The margin to put around the notification panel.
public void ChangeNotificationMargins(Thickness thickness)
{
NotificationMarginChanged?.Invoke(this, thickness);
}
///
/// Request that the notification alignment be changed.
///
/// The new horizontal alignment.
/// The new verical alignment.
public void ChangeNotificationAlignment(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
{
NotificationAlignmentChanged?.Invoke(this, (horizontalAlignment, verticalAlignment));
}
///
/// Dismisses the top notification and raises the next notification.
///
public void DismissNotification(int? index = null) => DismissNotificationInternal(index);
private void DismissNotificationInternal(int? index = null)
{
var targetNotification = _activeNotifications.ElementAtOrDefault(index ?? _pendingNotifications.Count - 1);
Guard.IsNotNull(targetNotification, nameof(targetNotification));
_activeNotifications.Remove(targetNotification);
NotificationDismissed?.Invoke(this, targetNotification);
targetNotification.Dismissed -= Notification_Dismissed;
FireIfReady();
}
///
/// Fires the next notification if there is space for it.
///
private void FireIfReady()
{
if (_pendingNotifications.Count > 0 && _activeNotifications.Count < MaxActiveNotifications)
{
var nextNotification = _pendingNotifications.FirstOrDefault();
if (nextNotification == null)
return;
_pendingNotifications.Remove(nextNotification);
_activeNotifications.Add(nextNotification);
NotificationRaised?.Invoke(this, nextNotification);
}
}
}
}