using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.BL.Entities;
using Tango.Core;
using Tango.Core.DI;
using Tango.FSE.Common.Connection;
using Tango.FSE.Common.Events;
using Tango.FSE.Common.Navigation;
using Tango.FSE.Common.Notifications;
using Tango.FSE.Common.Threading;
using Tango.FSE.UI.ViewModels;
using Tango.FSE.UI.Views;
namespace Tango.FSE.UI.Events
{
/// <summary>
/// Represents the <see cref="IEventsProvider"/> default implementation.
/// </summary>
/// <seealso cref="Tango.Core.ExtendedObject" />
/// <seealso cref="Tango.FSE.Common.Events.IEventsProvider" />
public class DefaultEventsProvider : ExtendedObject, IEventsProvider
{
private Dictionary<MachinesEvent, SnackbarItem> _snackbarItems;
private const int MAX_HISTORY = 100;
private IMachineProvider MachineProvider { get; set; }
[TangoInject]
private IDispatcherProvider Dispatcher { get; set; }
[TangoInject]
private INotificationProvider NotificationProvider { get; set; }
private INavigationManager NavigationManager { get; set; }
/// <summary>
/// Gets or sets the events history (resolved events).
/// </summary>
public ObservableCollection<MachinesEvent> EventsHistory { get; set; }
/// <summary>
/// Gets or sets the current active events.
/// </summary>
public ObservableCollection<MachinesEvent> ActiveEvents { get; set; }
/// <summary>
/// Gets or sets the active events view.
/// </summary>
public ICollectionView ActiveEventsView { get; set; }
/// <summary>
/// Gets or sets the events history view.
/// </summary>
public ICollectionView EventsHistoryView { get; set; }
/// <summary>
/// Gets a value indicating whether there are any active events currently.
/// </summary>
public bool HasActiveEvents
{
get { return ActiveEvents.Count > 0; }
}
/// <summary>
/// Initializes a new instance of the <see cref="DefaultEventsProvider"/> class.
/// </summary>
/// <param name="machineProvider">The machine provider.</param>
public DefaultEventsProvider(IMachineProvider machineProvider, INavigationManager navigationManager)
{
_snackbarItems = new Dictionary<MachinesEvent, SnackbarItem>();
//Active Events.
ActiveEvents = new ObservableCollection<MachinesEvent>();
ActiveEvents.CollectionChanged += ActiveEvents_CollectionChanged;
ActiveEventsView = CollectionViewSource.GetDefaultView(ActiveEvents);
ActiveEventsView.SortDescriptions.Add(new SortDescription(nameof(MachinesEvent.Category), ListSortDirection.Descending));
//Events History
EventsHistory = new ObservableCollection<MachinesEvent>();
EventsHistoryView = CollectionViewSource.GetDefaultView(EventsHistory);
EventsHistoryView.SortDescriptions.Add(new SortDescription(nameof(MachinesEvent.DateTime), ListSortDirection.Descending));
MachineProvider = machineProvider;
MachineProvider.MachineOperator.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
MachineProvider.MachineOperator.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;
MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected;
MachineProvider.MachineConnected += MachineProvider_MachineConnected;
NavigationManager = navigationManager;
NavigationManager.Navigating += NavigationManager_Navigating;
}
private void NavigationManager_Navigating(object sender, NavigationToEventArgs e)
{
if (e.ToVM != null && e.ToVM.GetType() == typeof(EventsViewVM))
{
foreach (var item in _snackbarItems.ToList())
{
NotificationProvider.PopSnackbarItem(item.Value);
_snackbarItems.Remove(item.Key);
}
}
}
private void MachineProvider_MachineConnected(object sender, MachineConnectedEventArgs e)
{
if (e.DifferentFromPrevious)
{
Dispatcher.Invoke(() =>
{
EventsHistory.Clear();
});
}
}
private void MachineProvider_MachineDisconnected(object sender, MachineDisconnectedEventArgs e)
{
Dispatcher.Invoke(() =>
{
ActiveEvents.Clear();
});
}
private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> events)
{
Dispatcher.Invoke(() =>
{
foreach (var ev in events.ToList())
{
ActiveEvents.Remove(ev);
EventsHistory.Insert(0, ev);
if (EventsHistory.Count > MAX_HISTORY)
{
EventsHistory.Remove(EventsHistory.Last());
}
if (_snackbarItems.ContainsKey(ev))
{
NotificationProvider.PopSnackbarItem(_snackbarItems[ev]);
_snackbarItems.Remove(ev);
}
}
});
}
private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable<MachinesEvent> events)
{
Dispatcher.Invoke(() =>
{
foreach (var ev in events.ToList())
{
ActiveEvents.Insert(0, ev);
if (NavigationManager.CurrentVM != null && NavigationManager.CurrentVM.GetType() == typeof(EventsViewVM))
{
continue;
}
MessageType messageType = MessageType.Info;
TimeSpan timeout = TimeSpan.FromSeconds(10);
switch (ev.Category)
{
case Tango.BL.Enumerations.EventTypeCategories.Info:
messageType = MessageType.Info;
break;
case Tango.BL.Enumerations.EventTypeCategories.Warning:
messageType = MessageType.Warning;
break;
case Tango.BL.Enumerations.EventTypeCategories.Error:
messageType = MessageType.Error;
break;
case Tango.BL.Enumerations.EventTypeCategories.Critical:
case Tango.BL.Enumerations.EventTypeCategories.Safety:
messageType = MessageType.Error;
timeout = TimeSpan.FromSeconds(30);
break;
}
var item = NotificationProvider.PushSnackbarItem(
messageType,
ev.EventType.Title,
true,
ev.EventType.Name + "\n" + ev.EventType.Description,
timeout,
null,
() =>
{
NavigationManager.NavigateWithObject<InternalModule, EventsView, EventsViewVM.NavigationObject>(new EventsViewVM.NavigationObject()
{
SelectedEvent = ev
});
});
_snackbarItems[ev] = item;
}
});
}
private void ActiveEvents_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged(nameof(HasActiveEvents));
}
}
}