using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core; using Tango.Core.DI; using Tango.FSE.BL; using Tango.FSE.Common.FSEApplication; using Tango.FSE.Common.Notifications; using Tango.Integration.Operation; using Tango.PMR.Diagnostics; namespace Tango.FSE.Common.Connection { /// /// Represents the default machine events state provider. /// /// public class FSEMachineEventsStateProvider : ExtendedObject, IMachineEventsStateProvider { private static Dictionary _eventTypesGuids; private bool _initialized; [TangoInject(TangoInjectMode.WhenAvailable)] private FSEServicesContainer Services { get; set; } [TangoInject(TangoInjectMode.WhenAvailable)] private INotificationProvider NotificationProvider { get; set; } private ReadOnlyObservableCollection _events; /// /// Gets the current machine events. /// public ReadOnlyObservableCollection Events { get { return _events; } private set { _events = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(HasEvents)); } } /// /// Gets or sets a value indicating whether this instance has events. /// public bool HasEvents { get { return Events.Count > 0; } } /// /// Occurs when new events are available. /// public event EventHandler> NewEvents; /// /// Occurs when a new events states has been received. /// public event EventHandler> EventsReceived; /// /// Occurs when old events has been resolved. /// public event EventHandler> EventsResolved; /// /// Occurs when the collection of current events has changed. /// public event EventHandler> EventsChanged; /// /// Initializes a new instance of the class. /// public FSEMachineEventsStateProvider() { TangoIOC.Default.Inject(this); Events = new ReadOnlyObservableCollection(new ObservableCollection(new Collection())); } /// /// Initializes this events state provider only if it was not initialized yet. /// Will retrieve all event types and perform caching and mapping between PMR and DB. /// public async void Init() { if (_initialized) return; _eventTypesGuids = new Dictionary(); try { var eventTypes = await Services.MachineEventsService.GetAllEventTypes(); foreach (var type in eventTypes) { try { _eventTypesGuids.Add((EventTypes)type.Code, type); } catch (Exception ex) { LogManager.Log(ex, $"Error initializing event type '{type.Name}'."); } } _initialized = true; } catch (Exception ex) { LogManager.Log(ex, "Error initializing FSE machine events state provider."); NotificationProvider.PushErrorReportingSnackbar(ex, "Events Initialization", "Error initializing machine events definitions."); } } /// /// Applies the collection of events received from the machine operator. /// /// The events. public void ApplyEvents(IEnumerable events) { List receivedEvents = new List(); foreach (var ev in events) { MachinesEvent machineEvent = new MachinesEvent(); machineEvent.DateTime = DateTime.UtcNow; machineEvent.Description = ev.Message; if (_eventTypesGuids.ContainsKey((EventTypes)ev.Type)) { machineEvent.EventType = _eventTypesGuids[(EventTypes)ev.Type]; } else { machineEvent.EventType = _eventTypesGuids[EventTypes.APPLICATION_INFORMATION]; } receivedEvents.Add(machineEvent); } List newEvents = receivedEvents.Where(x => !Events.ToList().Exists(y => y.Type == x.Type)).ToList(); List oldEvents = Events.Where(x => !receivedEvents.Exists(y => y.Type == x.Type)).ToList(); List activeEvents = Events.ToList(); foreach (var oldEvent in oldEvents) { oldEvent.ResolvedDateTime = DateTime.UtcNow; activeEvents.Remove(oldEvent); } foreach (var newEvent in newEvents) { activeEvents.Add(newEvent); } Events = new ReadOnlyObservableCollection(new ObservableCollection(activeEvents)); if (newEvents.Count > 0) { OnNewEvents(newEvents); } if (oldEvents.Count > 0) { OnEventsResolved(oldEvents); } if (newEvents.Count > 0 || oldEvents.Count > 0) { OnEventsChanged(_events); } OnEventsReceived(Events); RaisePropertyChanged(nameof(HasEvents)); } /// /// Called when the new has been events /// /// The events. protected virtual void OnNewEvents(IEnumerable events) { NewEvents?.Invoke(this, events); } /// /// Called when the events has been received /// /// The events. protected virtual void OnEventsReceived(IEnumerable events) { EventsReceived?.Invoke(this, events); } /// /// Called when the events has been resolved /// /// The events. protected virtual void OnEventsResolved(IEnumerable events) { EventsResolved?.Invoke(this, events); } /// /// Called when the events has been changed /// /// The events. protected virtual void OnEventsChanged(IEnumerable events) { EventsChanged?.Invoke(this, events); } /// /// Resets the current events tracking. /// public void Reset() { Events = new ReadOnlyObservableCollection(new ObservableCollection(new List())); RaisePropertyChanged(nameof(Events)); OnEventsChanged(new List()); } } }