using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.ComponentModel.Composition; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; using DTS.Common.Events; using DTS.Common.Events.TTSImport; using DTS.Common.Interface.DataRecorders; using DTS.Common.Interface.TestSetups.Imports.TTS.DIChannels; using DTS.Common.Interface.TestSetups.Imports.TTS.ReadFile; using Prism.Events; using Unity; using DTS.Common.Interactivity; using Prism.Regions; using Prism.Commands; using TTSImport.Model; using TTSImport.Resources; // ReSharper disable CheckNamespace // ReSharper disable MemberCanBePrivate.Global // ReSharper disable InconsistentNaming namespace TTSImport { /// /// this class handles Level Trigger edit/create functionality /// [PartCreationPolicy(CreationPolicy.Shared)] public class DigitalInputChannelsViewModel : IDigitalInputChannelsViewModel { /// /// The Hardware Scan view /// public IDigitalInputChannelsView View { get; set; } private IEventAggregator _eventAggregator { get; } private IRegionManager _regionManager; private IUnityContainer UnityContainer { get; } public InteractionRequest NotificationRequest { get; } public InteractionRequest ConfirmationRequest { get; } /// /// Creates a new instance of the TechnologyDomainEditViewModel. /// /// The IDigitalInputChannelsView. /// The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed. /// The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other. /// The unityContainer. public DigitalInputChannelsViewModel(IDigitalInputChannelsView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer) { View = view; View.DataContext = this; NotificationRequest = new InteractionRequest(); ConfirmationRequest = new InteractionRequest(); _eventAggregator = eventAggregator; UnityContainer = unityContainer; _regionManager = regionManager; _eventAggregator.GetEvent().Subscribe(OnRaiseNotification); _eventAggregator.GetEvent() .Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true); _eventAggregator.GetEvent().Subscribe(OnAssignedChannelsChangedEvent, ThreadOption.PublisherThread, true); _eventAggregator.GetEvent() .Subscribe(OnHardwareScanComplete, ThreadOption.PublisherThread, true); } #region Methods private void OnHardwareScanComplete(List hardware) { _hardware = hardware; } private void OnAssignedChannelsChangedEvent(ITTSSetup setup) { if (!Application.Current.Dispatcher.CheckAccess()) { Application.Current.Dispatcher.BeginInvoke(new Action(() => { OnAssignedChannelsChangedEvent(setup); })); return; } _setup = setup; if (null == _hardware || null == _setup) { return; } var channels = new ObservableCollection(); var remainingChannels = new ObservableCollection(); var channelIdToChannelRecord = new Dictionary(); foreach (var das in _hardware) { var ichannels = das.GetIHardwareChannels(); foreach (var ch in ichannels) { if (!ch.IsDigitalIn) { continue; } var newChannel = new DASChannel(ch); channels.Add(newChannel); channelIdToChannelRecord[ch.GetId()] = newChannel; } } foreach (var channelRecord in _setup.Channels) { if (channelRecord.IsEmptyRecord) { continue; } if (!channelRecord.IsDigitalInput) { continue; } if (!channelRecord.IsChannelCodeValid) { continue; } if (channelRecord.ChannelCode == TTSChannelRecord.NONE) { continue; } if (null != channelRecord.HardwareChannel && channelIdToChannelRecord.ContainsKey(channelRecord.HardwareChannel.GetId())) { channelIdToChannelRecord[channelRecord.HardwareChannel.GetId()].SetITTSChannelRecord(channelRecord); } else { remainingChannels.Add(channelRecord); } } DASChannels = channels; RemainingChannels = remainingChannels; OnPropertyChanged("DASChannels"); OnPropertyChanged("RemainingChannels"); } public void Cleanup() { } public Task CleanupAsync() { return Task.CompletedTask; } public void Initialize() { } public void Initialize(object parameter) { } public void Initialize(object parameter, object model) { } public Task InitializeAsync() { return Task.CompletedTask; } public Task InitializeAsync(object parameter) { return Task.CompletedTask; } public void Activated() { } /// /// Private Event handler for RaiseNotification event. /// private void OnBusyIndicatorNotification(bool eventArg) { IsBusy = eventArg; } /// /// Private Event handler for RaiseNotification event. /// private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle) { // The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window // Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string. var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "", eventArgsWithTitle.Image, string.Empty); NotificationRequest.Raise(new Notification { Content = eventArgsWithoutTitle, Title = eventArgsWithTitle.Title }); } #endregion #region Properties private ITTSSetup _setup; private IList _hardware; public bool IsDirty { get; private set; } private bool _isBusy; public bool IsBusy { get => _isBusy; set { _isBusy = value; OnPropertyChanged("IsBusy"); } } private bool _isMenuIncluded; public bool IsMenuIncluded { get => _isMenuIncluded; set { _isMenuIncluded = value; OnPropertyChanged("IsMenuIncluded"); } } private bool _isNavigationIncluded; public bool IsNavigationIncluded { get => _isNavigationIncluded; set { _isNavigationIncluded = value; OnPropertyChanged("IsNavigationIncluded"); } } public bool AssignEnabled { get; set; } public bool RemoveEnabled { get; set; } public bool EnableOrDisableEnabled { get; set; } public ObservableCollection DASChannels { get; set; } = new ObservableCollection(); public ObservableCollection RemainingChannels { get; set; } = new ObservableCollection(); private ITTSChannelRecord _selectedRemainingChannel; public ITTSChannelRecord SelectedRemainingChannel { get => _selectedRemainingChannel; set { _selectedRemainingChannel = value; if (null == _selectedRemainingChannel || null == SelectedDASChannel) return; AssignEnabled = true; OnPropertyChanged("AssignEnabled"); } } private DASChannel _selectedDASChannel; public DASChannel SelectedDASChannel { get => _selectedDASChannel; set { _selectedDASChannel = value; DetermineRemoveEnableStatus(); } } private void DetermineRemoveEnableStatus() { if (_selectedDASChannel?.Channel != null) { if (!string.IsNullOrWhiteSpace(_selectedDASChannel.EID) && _selectedDASChannel.EID == _selectedDASChannel.Channel.SensorEID) { //can only be replaced, can't be removed RemoveEnabled = false; } RemoveEnabled = true; } else { RemoveEnabled = false; } OnPropertyChanged("RemoveEnabled"); AssignEnabled = null != _selectedDASChannel && null != _selectedRemainingChannel; OnPropertyChanged("AssignEnabled"); EnableOrDisableEnabled = _selectedDASChannel?.Channel != null; OnPropertyChanged("EnableOrDisableEnabled"); OnPropertyChanged("EnableOrDisableText"); } public string EnableOrDisableText { get { if (SelectedDASChannel?.Channel == null) { return StringResources.Analog_Enable; } return SelectedDASChannel.Channel.Disabled ? StringResources.Analog_Enable : StringResources.Analog_Disable; } } #endregion Properties #region Commands #region assign /// /// Assign a channel code to a channel /// private DelegateCommand _assignCommand; public DelegateCommand AssignCommand => _assignCommand ?? (_assignCommand = new DelegateCommand(Assign)); private void Assign() { if (SelectedRemainingChannel == null) { return; } _eventAggregator.GetEvent().Publish(_setup); //BEFORE we go any further, check the state of sensor ids //if the channel has a sensor id AND there's a sensor on the channel with the same id //then prompt on replacing the id //IF the channel has a sensor id and there's no sensor on the channel BUT the new sensor has a different id //then prompt on replacing the id var bReplacingID = false; if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID)) { if (null != SelectedRemainingChannel && SelectedRemainingChannel.SensorEID != SelectedDASChannel.EID) { bReplacingID = true; } //if existing channel has this ID, we will need to clear out the old id and assign a new one... if (null != SelectedDASChannel.Channel && SelectedDASChannel.Channel.SensorEID == SelectedDASChannel.EID) { bReplacingID = true; } } if (bReplacingID) { Task.Run(() => { var dialogResult = MessageBox.Show(StringResources.AssignSensorPrompt, StringResources.UserFeedbackRequired, MessageBoxButton.YesNo); if (dialogResult == MessageBoxResult.Yes) { Application.Current.Dispatcher.BeginInvoke(new Action(AssignWork)); } }); return; } AssignWork(); } /// /// assigns a channel record to a physical channel /// private void AssignWork() { if (null != SelectedDASChannel.Channel) { if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID)) { SelectedDASChannel.Channel.SensorEID = ""; } RemainingChannels.Add(SelectedDASChannel.Channel); } if (!string.IsNullOrWhiteSpace(SelectedDASChannel.EID)) { SelectedRemainingChannel.SensorEID = SelectedDASChannel.EID; } SelectedRemainingChannel.DigitalInputMode = DTS.Common.Enums.DigitalInputModes.CCNO; SelectedDASChannel.SetITTSChannelRecord(SelectedRemainingChannel); var channel = SelectedRemainingChannel; var index = RemainingChannels.IndexOf(channel); SelectedRemainingChannel = null; RemainingChannels.Remove(channel); CollectionViewSource.GetDefaultView(DASChannels)?.Refresh(); if (index < RemainingChannels.Count) { SelectedRemainingChannel = RemainingChannels[index]; OnPropertyChanged("SelectedRemainingChannel"); } else if (RemainingChannels.Count > 0) { SelectedRemainingChannel = RemainingChannels[index - 1]; OnPropertyChanged("SelectedRemainingChannel"); } index = DASChannels.IndexOf(SelectedDASChannel); for (var i = index; i < DASChannels.Count; i++) { var dasChannel = DASChannels[i]; if (null != dasChannel.Channel) { continue; } SelectedDASChannel = dasChannel; OnPropertyChanged("SelectedDASChannel"); return; } //didn't find a match, start from the beginning? for (var i = 0; i < index; i++) { var dasChannel = DASChannels[i]; if (null != dasChannel.Channel) { continue; } SelectedDASChannel = dasChannel; OnPropertyChanged("SelectedDASChannel"); return; } //if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status OnPropertyChanged("SelectedDASChannel"); DetermineRemoveEnableStatus(); } #endregion #region remove private DelegateCommand _removeCommand; public DelegateCommand RemoveCommand => _removeCommand ?? (_removeCommand = new DelegateCommand(Remove)); /// /// remove a hardware channel assignment (does not remove the channel from the test setup though?) /// private void Remove() { if (null == SelectedDASChannel || null == SelectedDASChannel.Channel) { return; } _eventAggregator.GetEvent().Publish(_setup); RemainingChannels.Add(SelectedDASChannel.Channel); SelectedDASChannel.SetITTSChannelRecord(null); CollectionViewSource.GetDefaultView(DASChannels)?.Refresh(); var index = DASChannels.IndexOf(SelectedDASChannel); for (var i = index; i < DASChannels.Count; i++) { if (null == DASChannels[i].Channel) { continue; } SelectedDASChannel = DASChannels[i]; OnPropertyChanged("SelectedDASChannel"); return; } for (var i = 0; i < index; i++) { if (null == DASChannels[i].Channel) { continue; } SelectedDASChannel = DASChannels[i]; OnPropertyChanged("SelectedDASChannel"); return; } //if we get here there's no new channel to go to, but we need to set the remove/enable/disable button status OnPropertyChanged("SelectedDASChannel"); DetermineRemoveEnableStatus(); } #endregion #region enableordisable private DelegateCommand _enableOrDisableCommand; public DelegateCommand EnableOrDisableCommand => _enableOrDisableCommand ?? (_enableOrDisableCommand = new DelegateCommand(EnableOrDisable)); /// /// enables or disables a channel in the test. /// private void EnableOrDisable() { if (SelectedDASChannel?.Channel == null) { return; } SelectedDASChannel.Channel.Disabled = !SelectedDASChannel.Channel.Disabled; SelectedDASChannel.Disabled = SelectedDASChannel.Channel.Disabled; OnPropertyChanged("EnableOrDisableText"); _eventAggregator.GetEvent().Publish(_setup); } #endregion #endregion /// /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }