using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Tango.PPC.Common.Notifications;
using Tango.Core;
using System.Collections.Concurrent;
using System.Windows.Media.Imaging;
using Tango.SharedUI.Helpers;
using System.Timers;
using Tango.Core.Commands;
using Tango.Touch.Controls;
using Tango.SharedUI;
using System.Reflection;
using Tango.Core.DI;
using System.ComponentModel;
using System.Windows.Data;
using Tango.Logging;
namespace Tango.PPC.UI.Notifications
{
///
/// Represents the default PPC notification provider.
///
///
///
public class DefaultNotificationProvider : ExtendedObject, INotificationProvider
{
private ConcurrentQueue> _pendingMessageBoxes;
private ConcurrentQueue> _pendingDialogs;
private List _appButtons;
private bool _notificationsVisible;
///
/// Gets or sets a value indicating whether to allow notifications visibility.
///
public bool NotificationsVisible
{
get { return _notificationsVisible; }
set { _notificationsVisible = value; RaisePropertyChangedAuto(); }
}
///
/// Gets the collection of notification items.
///
public ObservableCollection NotificationItems { get; private set; }
///
/// Gets the application bar items.
///
public ObservableCollection AppBarItems { get; private set; }
///
/// Gets the notification items view.
///
public ICollectionView NotificationItemsView { get; private set; }
///
/// Gets the collection of taskbar items.
///
public ObservableCollection TaskBarItems { get; private set; }
///
/// Initializes a new instance of the class.
///
public DefaultNotificationProvider()
{
NotificationsVisible = true;
NotificationItems = new ObservableCollection();
AppBarItems = new ObservableCollection();
CollectionViewSource.GetDefaultView(AppBarItems).SortDescriptions.Add(new SortDescription(nameof(AppBarItem.Priority), ListSortDirection.Ascending));
TaskBarItems = new ObservableCollection();
_pendingMessageBoxes = new ConcurrentQueue>();
_pendingDialogs = new ConcurrentQueue>();
_appButtons = new List();
PopNotificationCommand = new RelayCommand((x) => PopNotification(x));
NotificationItems.EnableCrossThreadOperations();
NotificationItemsView = CollectionViewSource.GetDefaultView(NotificationItems);
NotificationItemsView.SortDescriptions.Add(new SortDescription(nameof(NotificationItem.Priority), ListSortDirection.Descending));
}
private MessageBoxVM _currentMessageBox;
///
/// Gets the current message box if any.
///
public MessageBoxVM CurrentMessageBox
{
get { return _currentMessageBox; }
private set
{
_currentMessageBox = value;
RaisePropertyChangedAuto();
RaisePropertyChanged(nameof(HasMessageBox));
RaisePropertyChanged(nameof(HasDialogOrMessage));
}
}
///
/// Gets a value indicating whether a message box is available.
///
public bool HasMessageBox
{
get
{
return CurrentMessageBox != null;
}
}
private FrameworkElement _currentDialog;
///
/// Gets the current dialog if any.
///
public FrameworkElement CurrentDialog
{
get { return _currentDialog; }
private set
{
_currentDialog = value;
RaisePropertyChangedAuto();
RaisePropertyChanged(nameof(HasDialog));
RaisePropertyChanged(nameof(HasDialogOrMessage));
}
}
private AppButton _currentAppButton;
///
/// Gets the current app button.
///
public AppButton CurrentAppButton
{
get { return _currentAppButton; }
private set { _currentAppButton = value; RaisePropertyChangedAuto(); }
}
///
/// Gets a value indicating whether a dialog is available.
///
public bool HasDialog
{
get
{
return CurrentDialog != null;
}
}
public bool HasDialogOrMessage
{
get
{
return HasDialog || HasMessageBox;
}
}
///
/// Shows an error message box.
///
/// The message.
///
public Task ShowError(string message)
{
return ShowMessageBox(new MessageBoxVM()
{
Message = message,
Icon = TouchIconKind.AlertCircleOutline,
Title = "Error",
Brush = Application.Current.Resources["TangoMessageBoxErrorBrush"] as Brush,
HeaderBrush = Application.Current.Resources["TangoMessageBoxHeaderErrorBrush"] as Brush,
});
}
///
/// Shows an information message box.
///
/// The message.
///
public Task ShowInfo(string message)
{
return ShowMessageBox(new MessageBoxVM()
{
Message = message,
Icon = TouchIconKind.AlertCircleOutline,
Title = "Information",
Brush = Application.Current.Resources["TangoMessageBoxInfoBrush"] as Brush,
HeaderBrush = Application.Current.Resources["TangoMessageBoxHeaderInfoBrush"] as Brush,
});
}
///
/// Shows warning message box.
///
/// The message.
///
public Task ShowWarning(string message)
{
return ShowMessageBox(new MessageBoxVM()
{
Message = message,
Icon = TouchIconKind.AlertCircleOutline,
Title = "Warning",
Brush = Application.Current.Resources["TangoMessageBoxWarningBrush"] as Brush,
HeaderBrush = Application.Current.Resources["TangoMessageBoxHeaderWarningBrush"] as Brush,
});
}
///
/// Shows a question message box.
///
/// The message.
///
public Task ShowQuestion(string message)
{
return ShowMessageBox(new MessageBoxVM()
{
Message = message,
Icon = TouchIconKind.QuestionCircleRegular,
Title = "Confirm",
HasCancel = true,
Brush = Application.Current.Resources["TangoMessageBoxQuestionBrush"] as Brush,
HeaderBrush = Application.Current.Resources["TangoMessageBoxHeaderQuestionBrush"] as Brush,
});
}
///
/// Shows a success message box.
///
/// The message.
///
public Task ShowSuccess(string message)
{
return ShowMessageBox(new MessageBoxVM()
{
Message = message,
Icon = TouchIconKind.Check,
Title = "Success",
Brush = Application.Current.Resources["TangoMessageBoxSuccessBrush"] as Brush,
HeaderBrush = Application.Current.Resources["TangoMessageBoxHeaderSuccessBrush"] as Brush,
});
}
///
/// Shows the message box.
///
/// The view model.
///
private Task ShowMessageBox(MessageBoxVM vm)
{
ReleaseGlobalBusyMessage();
LogManager.Log($"Displaying MessagBox '{vm.Message}'.");
TaskCompletionSource source = new TaskCompletionSource();
vm.Accepted += () => { OnMessageBoxClosed(); source.SetResult(true); };
vm.Canceled += () => { OnMessageBoxClosed(); source.SetResult(false); };
if (CurrentMessageBox == null)
{
CurrentMessageBox = vm;
}
else
{
_pendingMessageBoxes.Enqueue(new PendingNotification(vm, source));
}
return source.Task;
}
///
/// Called when the message box has been closed.
///
private void OnMessageBoxClosed()
{
LogManager.Log("MessageBox closed.");
CurrentMessageBox = null;
if (_pendingMessageBoxes.Count > 0)
{
PendingNotification p = null;
if (_pendingMessageBoxes.TryDequeue(out p))
{
CurrentMessageBox = p.Item;
}
}
}
///
/// Inserts the notification item to the bottom of the notifications collection.
///
/// The item.
///
public NotificationItem PushNotification(NotificationItem item)
{
item.Time = DateTime.Now;
LogManager.Log($"Pushing NotificationItem '{item.GetType().Name}'.");
item.RemoveAction = () => { PopNotification(item); };
NotificationItems.Insert(0, item);
RaisePropertyChanged(nameof(HasNotificationItems));
RaisePropertyChanged(nameof(NotificationItems));
return item;
}
///
/// Pushes the notification.
///
///
///
public NotificationItem PushNotification() where T : NotificationItem
{
return PushNotification(Activator.CreateInstance());
}
///
/// Removed the specified notification item.
///
/// The item.
public void PopNotification(NotificationItem item)
{
LogManager.Log($"Popping out NotificationItem '{item.GetType().Name}'.");
NotificationItems.Remove(item);
RaisePropertyChanged(nameof(HasNotificationItems));
RaisePropertyChanged(nameof(NotificationItems));
}
///
/// Gets a value indicating whether this instance has notification items.
///
public bool HasNotificationItems
{
get
{
return NotificationItems.Count > 0;
}
}
///
/// Gets the pop notification command.
///
public RelayCommand PopNotificationCommand { get; private set; }
///
/// Displays the specified dialog in a modal design.
///
///
/// The data context.
/// The view.
///
public async Task ShowDialog(T datacontext, FrameworkElement view) where T : DialogViewVM
{
TaskCompletionSource source = new TaskCompletionSource();
InvokeUI(() =>
{
view.DataContext = datacontext;
TangoIOC.Default.Inject(datacontext);
view.Loaded += (_, __) =>
{
view.DataContext = datacontext;
datacontext.OnShow();
};
datacontext.Accepted += () => { OnDialogClosed(); source.SetResult(datacontext); };
datacontext.Canceled += () => { OnDialogClosed(); source.SetResult(datacontext); };
if (CurrentDialog == null)
{
CurrentDialog = view;
}
else
{
_pendingDialogs.Enqueue(new PendingNotification(new DialogAndView(datacontext, view), source));
}
});
var result = await source.Task;
return result as T;
}
///
/// Called when [dialog closed].
///
private void OnDialogClosed()
{
CurrentDialog = null;
if (_pendingDialogs.Count > 0)
{
PendingNotification p = null;
if (_pendingDialogs.TryDequeue(out p))
{
CurrentDialog = p.Item.View;
}
}
}
///
/// Displays the specified dialog in a modal design.
/// The notification provider will try to locate the view automatically using conventions.
///
///
/// The data context.
///
public Task ShowDialog(T datacontext) where T : DialogViewVM
{
TaskCompletionSource source = new TaskCompletionSource();
InvokeUI(async () =>
{
var callingAssembly = datacontext.GetType().Assembly;
String viewName = datacontext.GetType().FullName.Replace("VM", "");
var viewType = callingAssembly.GetType(viewName);
if (viewType == null)
{
throw new NullReferenceException("View type for " + datacontext.GetType().Name + " could not be found!");
}
var view = Activator.CreateInstance(viewType) as FrameworkElement;
if (view == null)
{
throw new NullReferenceException("The view " + viewType.ToString() + " is not of type framework element.");
}
T result = await ShowDialog(datacontext, view);
source.SetResult(result);
});
return source.Task;
}
///
/// Displays the specified dialog in a modal design.
/// The data context instance will be automatically created.
/// The notification provider will try to locate the view automatically using conventions.
///
///
///
public Task ShowDialog() where T : DialogViewVM
{
TaskCompletionSource source = new TaskCompletionSource();
InvokeUI(async () =>
{
var result = await ShowDialog(Activator.CreateInstance());
source.SetResult(result);
});
return source.Task;
}
///
/// Sets the global busy message.
///
/// The message.
public void SetGlobalBusyMessage(string message)
{
GlobalBusyMessage = message;
IsInGlobalBusyState = true;
RaisePropertyChanged(nameof(IsInGlobalBusyState));
RaisePropertyChanged(nameof(GlobalBusyMessage));
}
///
/// Releases the global busy message.
///
public void ReleaseGlobalBusyMessage()
{
GlobalBusyMessage = null;
IsInGlobalBusyState = false;
RaisePropertyChanged(nameof(IsInGlobalBusyState));
RaisePropertyChanged(nameof(GlobalBusyMessage));
}
///
/// Gets the current global busy message.
///
public string GlobalBusyMessage { get; private set; }
///
/// Gets a value indicating whether this instance is in global busy state.
///
public bool IsInGlobalBusyState { get; private set; }
///
/// Gets a value indicating whether this instance has application bar item.
///
public bool HasAppBarItems
{
get { return AppBarItems.Count > 0; }
}
///
/// Pushes the application bar item.
///
/// The application bar item.
///
public AppBarItem PushAppBarItem(AppBarItem appBarItem)
{
LogManager.Log($"Pushing AppBarItem '{appBarItem.GetType().Name}'.");
AppBarItems.Add(appBarItem);
appBarItem.RemoveAction = () => PopAppBarItem(appBarItem);
RaisePropertyChanged(nameof(HasAppBarItems));
return appBarItem;
}
///
/// Pushes the application bar item.
///
///
///
public T PushAppBarItem() where T : AppBarItem
{
return PushAppBarItem(Activator.CreateInstance()) as T;
}
///
/// Pops the application bar item.
///
/// The application bar item.
public void PopAppBarItem(AppBarItem appBarItem)
{
InvokeUI(() =>
{
LogManager.Log($"Popping out AppBarItem '{appBarItem.GetType().Name}'.");
AppBarItems.Remove(appBarItem);
RaisePropertyChanged(nameof(HasAppBarItems));
});
}
///
/// Pushes the task bar item.
///
/// The task bar item.
///
public TaskBarItem PushTaskBarItem(TaskBarItem taskBarItem)
{
TaskBarItems.Add(taskBarItem);
return taskBarItem;
}
///
/// Handles the Push Task Bar Item event.
///
///
///
public TaskBarItem PushTaskBarItem() where T : TaskBarItem
{
return PushTaskBarItem(Activator.CreateInstance());
}
///
/// Pops the task bar item.
///
///
public void PopTaskBarItem(TaskBarItem taskBarItem)
{
TaskBarItems.Remove(taskBarItem);
}
///
/// Pushes the app button.
///
/// The app button.
public void PushAppButton(AppButton appButton)
{
if (appButton != null)
{
LogManager.Log($"Pushing app button '{appButton.GetType().Name}'...");
}
_appButtons.Insert(0, appButton);
CurrentAppButton = appButton;
}
///
/// Pops the app button.
///
/// The app button.
public void PopAppButton(AppButton appButton)
{
if (appButton != null)
{
LogManager.Log($"Popping app button '{appButton.GetType().Name}'...");
}
else
{
LogManager.Log("Popping app button 'null' ??", LogCategory.Warning);
}
_appButtons.RemoveAll(x => x == appButton);
CurrentAppButton = _appButtons.FirstOrDefault();
}
}
}