using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core.Commands; using Tango.Core.DI; using Tango.Core.ExtensionMethods; using Tango.PPC.Common; using Tango.PPC.Common.Connection; using Tango.PPC.Common.ExternalBridge; using Tango.PPC.Common.Lubrication; using Tango.PPC.Common.Messages; using Tango.PPC.Common.OS; using Tango.PPC.Common.UWF; using Tango.SharedUI.Components; using Tango.WiFi; namespace Tango.PPC.MachineSettings.ViewModels { /// /// Represents the main view VM and entry point for . /// /// public class MainViewVM : PPCViewModel { private TimeZoneInfo _previousTimeZone; private bool _previousEnableUWF; #region Classes public class RmlLubricationLevelSettings : RmlLubricationLevel { public String Name { get; set; } public RmlLubricationLevelSettings() { } public RmlLubricationLevelSettings(RmlLubricationLevel rmlLevel, String name) { RmlGuid = rmlLevel.RmlGuid; LubricationLevel = rmlLevel.LubricationLevel; Name = name; } public RmlLubricationLevel ToRmlLubricationLevel() { return new RmlLubricationLevel() { RmlGuid = RmlGuid, LubricationLevel = LubricationLevel, }; } } #endregion #region Properties [TangoInject] private IOperationSystemManager OperationSystemManager { get; set; } [TangoInject] private IUnifiedWriteFilterManager UnifiedWriteFilterManager { get; set; } private Machine _machine; public Machine Machine { get { return _machine; } set { _machine = value; RaisePropertyChangedAuto(); } } private SelectedObjectCollection _selectedJobTypes; public SelectedObjectCollection SelectedJobTypes { get { return _selectedJobTypes; } set { _selectedJobTypes = value; RaisePropertyChangedAuto(); } } private SelectedObjectCollection _selectedColorSpaces; public SelectedObjectCollection SelectedColorSpaces { get { return _selectedColorSpaces; } set { _selectedColorSpaces = value; RaisePropertyChangedAuto(); } } private ObservableCollection _rmls; public ObservableCollection Rmls { get { return _rmls; } set { _rmls = value; RaisePropertyChangedAuto(); } } private bool _enableHotSpot; public bool EnableHotSpot { get { return _enableHotSpot; } set { _enableHotSpot = value; RaisePropertyChangedAuto(); OnEnableHotSpotChanged(); } } private String _hotSpotPassword; public String HotSpotPassword { get { return _hotSpotPassword; } set { _hotSpotPassword = value; RaisePropertyChangedAuto(); } } private bool _enableExternalBridge; public bool EnableExternalBridge { get { return _enableExternalBridge; } set { _enableExternalBridge = value; RaisePropertyChangedAuto(); OnEnableExternalBridgeChanged(); } } private String _externalBridgePassword; public String ExternalBridgePassword { get { return _externalBridgePassword; } set { _externalBridgePassword = value; RaisePropertyChangedAuto(); } } private bool _enableRemoteAssistance; public bool EnableRemoteAssistance { get { return _enableRemoteAssistance; } set { _enableRemoteAssistance = value; RaisePropertyChangedAuto(); OnEnableRemoteAssistanceChanged(); } } private bool _enableLockScreen; public bool EnableLockScreen { get { return _enableLockScreen; } set { _enableLockScreen = value; RaisePropertyChangedAuto(); } } private int _lockScreenTimeoutMinutes; public int LockScreenTimeoutMinutes { get { return _lockScreenTimeoutMinutes; } set { _lockScreenTimeoutMinutes = value; RaisePropertyChangedAuto(); } } private String _lockScreenPassword; public String LockScreenPassword { get { return _lockScreenPassword; } set { _lockScreenPassword = value; RaisePropertyChangedAuto(); } } private Rml _defaultRML; public Rml DefaultRML { get { return _defaultRML; } set { _defaultRML = value; RaisePropertyChangedAuto(); } } private SpoolType _defaultSpoolType; public SpoolType DefaultSpoolType { get { return _defaultSpoolType; } set { _defaultSpoolType = value; RaisePropertyChangedAuto(); } } private bool _synchronizeJobs; public bool SynchronizeJobs { get { return _synchronizeJobs; } set { _synchronizeJobs = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private bool _synchronizeDiagnostics; public bool SynchronizeDiagnostics { get { return _synchronizeDiagnostics; } set { _synchronizeDiagnostics = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private bool _autoCheckForUpdates; public bool AutoCheckForUpdates { get { return _autoCheckForUpdates; } set { _autoCheckForUpdates = value; RaisePropertyChangedAuto(); } } private List _timeZones; /// /// Gets or sets the available time zones. /// public List TimeZones { get { return _timeZones; } set { _timeZones = value; RaisePropertyChangedAuto(); } } private TimeZoneInfo _selectedTimeZone; /// /// Gets or sets the selected time zone. /// public TimeZoneInfo SelectedTimeZone { get { return _selectedTimeZone; } set { _selectedTimeZone = value; RaisePropertyChangedAuto(); } } private bool _enableUWF; public bool EnableUWF { get { return _enableUWF; } set { _enableUWF = value; RaisePropertyChangedAuto(); } } private List _lubricationLevels; public List LubricationLevels { get { return _lubricationLevels; } set { _lubricationLevels = value; RaisePropertyChangedAuto(); } } private RmlLubricationLevelSettings _selectedLubricationLevel; public RmlLubricationLevelSettings SelectedLubricationLevel { get { return _selectedLubricationLevel; } set { _selectedLubricationLevel = value; RaisePropertyChangedAuto(); } } #endregion #region Commands /// /// Gets or sets the save command. /// public RelayCommand SaveCommand { get; set; } /// /// Gets or sets the discard command. /// public RelayCommand DiscardCommand { get; set; } /// /// Gets or sets the synchronize command. /// public RelayCommand SynchronizeCommand { get; set; } #endregion public MainViewVM() { LubricationLevels = new List(); SaveCommand = new RelayCommand(Save); DiscardCommand = new RelayCommand(Discard); SynchronizeCommand = new RelayCommand(Synchronize, () => !MachineDataSynchronizer.IsSynchronizing && IsFree); } private void Discard() { NavigationManager.NavigateBack(); } private async void Save() { if (Validate()) { Settings.SupportedJobTypes = SelectedJobTypes.SynchedSource.ToList(); Settings.SupportedColorSpaces = SelectedColorSpaces.SynchedSource.ToList(); Machine.MapPropertiesTo(MachineProvider.Machine, MappingFlags.NoReferenceTypes); Settings.EnableHotSpot = EnableHotSpot; Settings.HotSpotPassword = HotSpotPassword; Settings.EnableExternalBridge = EnableExternalBridge; Settings.ExternalBridgePassword = ExternalBridgePassword; Settings.EnableLockScreen = EnableLockScreen; Settings.LockScreenTimeout = TimeSpan.FromMinutes(LockScreenTimeoutMinutes); Settings.LockScreenPassword = LockScreenPassword; Settings.DefaultRmlGuid = DefaultRML?.Guid; Settings.DefaultSpoolTypeGuid = DefaultSpoolType?.Guid; Settings.SynchronizeJobs = SynchronizeJobs; Settings.SynchronizeDiagnostics = SynchronizeDiagnostics; Settings.AutoCheckForUpdates = AutoCheckForUpdates; Settings.LubricationLevels = LubricationLevels.Where(x => x.LubricationLevel != LubricationLevel.Standard).Select(x => x.ToRmlLubricationLevel()).ToList(); MachineDataSynchronizer.IsEnabled = SynchronizeJobs || SynchronizeDiagnostics; Settings.Save(); await MachineProvider.SaveMachine(); bool isRestarting = false; if (_previousTimeZone.ToStringSafe() != SelectedTimeZone.ToStringSafe()) { if (await NotificationProvider.ShowQuestion("Changing the time zone requires the application to restart. Do you wish to restart the application?")) { try { LogManager.Log($"Setting new time zone to '{SelectedTimeZone.ToString()}'."); NotificationProvider.SetGlobalBusyMessage("Setting new time zone..."); await OperationSystemManager.ChangeTimeZone(SelectedTimeZone); NotificationProvider.ReleaseGlobalBusyMessage(); isRestarting = true; ApplicationManager.Restart(); } catch (Exception ex) { LogManager.Log(ex, "Error changing the time zone."); NotificationProvider.ReleaseGlobalBusyMessage(); await NotificationProvider.ShowError($"Error setting timezone.\n{ex.FlattenMessage()}"); } } } if (_previousEnableUWF != EnableUWF) { await NotificationProvider.ShowWarning("Changes to disk protection (UWF) will take effect only after a full system restart."); try { LogManager.Log($"Changing UWF mode to '{EnableUWF}'."); if (EnableUWF) { NotificationProvider.SetGlobalBusyMessage("Enabling disk protection (UWF)..."); await UnifiedWriteFilterManager.Enable(); } else { NotificationProvider.SetGlobalBusyMessage("Disabling disk protection (UWF)..."); await UnifiedWriteFilterManager.Disable(); } NotificationProvider.ReleaseGlobalBusyMessage(); } catch (Exception ex) { NotificationProvider.ReleaseGlobalBusyMessage(); LogManager.Log(ex, "Error setting UWF mode."); await NotificationProvider.ShowError($"Could not change the disk protection mode\n{ex.FlattenMessage()}"); } } if (!isRestarting) { await NavigationManager.NavigateBack(); } } } protected override void OnValidating() { base.OnValidating(); } /// /// Called when the application has been started /// public override void OnApplicationStarted() { try { TimeZones = OperationSystemManager.GetAvailableTimeZones().ToList(); } catch (Exception ex) { LogManager.Log(ex, "Error retrieving available time zones."); } } public async override void OnApplicationReady() { base.OnApplicationReady(); MachineDataSynchronizer.SynchronizationStarted += (_, __) => InvalidateRelayCommands(); MachineDataSynchronizer.SynchronizationEnded += (_, __) => InvalidateRelayCommands(); using (ObservablesContext db = ObservablesContext.CreateDefault()) { Rmls = await new RmlsCollectionBuilder(db).SetAll().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync(); } } public async override void OnNavigatedTo() { base.OnNavigatedTo(); Machine = MachineProvider.Machine.ShallowClone(); RaisePropertyChanged(nameof(Machine)); _enableHotSpot = HotSpotProvider.IsEnabled; RaisePropertyChanged(nameof(EnableHotSpot)); HotSpotPassword = Settings.HotSpotPassword; _enableExternalBridge = ExternalBridgeService.Enabled; RaisePropertyChanged(nameof(EnableExternalBridge)); ExternalBridgePassword = Settings.ExternalBridgePassword; _enableRemoteAssistance = RemoteAssistanceProvider.IsEnabled; RaisePropertyChanged(nameof(EnableRemoteAssistance)); EnableLockScreen = Settings.EnableLockScreen; LockScreenTimeoutMinutes = (int)Settings.LockScreenTimeout.TotalMinutes; LockScreenPassword = Settings.LockScreenPassword; SelectedJobTypes = new SelectedObjectCollection(Enum.GetValues(typeof(JobTypes)).Cast().ToObservableCollection(), Settings.SupportedJobTypes.ToObservableCollection()); SelectedColorSpaces = new SelectedObjectCollection(Enum.GetValues(typeof(ColorSpaces)).Cast().Where(x => x.IsUserSpace()).ToObservableCollection(), Settings.SupportedColorSpaces.ToObservableCollection()); DefaultRML = Rmls.SingleOrDefault(x => x.Guid == Settings.DefaultRmlGuid); DefaultSpoolType = Adapter.SpoolTypes.SingleOrDefault(x => x.Guid == Settings.DefaultSpoolTypeGuid); SynchronizeJobs = Settings.SynchronizeJobs; SynchronizeDiagnostics = Settings.SynchronizeDiagnostics; AutoCheckForUpdates = Settings.AutoCheckForUpdates; SelectedTimeZone = TimeZones.SingleOrDefault(x => x.StandardName == TimeZone.CurrentTimeZone.StandardName); _previousTimeZone = SelectedTimeZone; try { EnableUWF = await UnifiedWriteFilterManager.IsEnabled(); _previousEnableUWF = EnableUWF; } catch (Exception ex) { LogManager.Log(ex, "Error getting UWF status."); } try { List levels = new List(); foreach (var rml in Rmls) { RmlLubricationLevel userLevel = Settings.LubricationLevels.FirstOrDefault(x => x.RmlGuid == rml.Guid); RmlLubricationLevelSettings rmlLevel = new RmlLubricationLevelSettings(); rmlLevel.RmlGuid = rml.Guid; rmlLevel.Name = rml.Name; rmlLevel.LubricationLevel = userLevel != null ? userLevel.LubricationLevel : LubricationLevel.Standard; levels.Add(rmlLevel); } LubricationLevels = levels; if (SelectedLubricationLevel != null) { SelectedLubricationLevel = LubricationLevels.FirstOrDefault(x => x.RmlGuid == SelectedLubricationLevel.RmlGuid); } else { SelectedLubricationLevel = LubricationLevels.FirstOrDefault(); } } catch (Exception ex) { LogManager.Log(ex, "Error loading lubrication levels."); } } private async void OnEnableRemoteAssistanceChanged() { if (EnableRemoteAssistance) { try { await RemoteAssistanceProvider.EnableRemoteAssistance(); } catch { await NotificationProvider.ShowError("An error occurred while trying to activate the remote assistance service. Please check your device settings and try again."); _enableRemoteAssistance = false; } } else { try { await RemoteAssistanceProvider.DisableRemoteAssistance(); } catch { await NotificationProvider.ShowError("An error occurred while trying to deactivate the remote assistance service. Please check your device settings and try again."); _enableRemoteAssistance = true; } } RaisePropertyChanged(nameof(EnableRemoteAssistance)); } private async void OnEnableHotSpotChanged() { if (EnableHotSpot) { if (HotSpotPassword == null || HotSpotPassword.Length < 8 || HotSpotPassword.Length > 16) { await NotificationProvider.ShowError("Hot spot requires a password of 8 to 16 characters."); _enableHotSpot = false; RaisePropertyChanged(nameof(EnableHotSpot)); return; } try { await HotSpotProvider.EnableHotSpot(HotSpotPassword); } catch { await NotificationProvider.ShowError("An error occurred while trying to activate the hot spot network. Please check your device settings and try again."); _enableHotSpot = false; } } else { try { await HotSpotProvider.DisableHotSpot(); } catch { await NotificationProvider.ShowError("An error occurred while trying to deactivate the hot spot network."); _enableHotSpot = true; } } RaisePropertyChanged(nameof(EnableHotSpot)); } private void OnEnableExternalBridgeChanged() { ExternalBridgeService.Enabled = EnableExternalBridge; } private async void Synchronize() { try { IsFree = false; NotificationProvider.SetGlobalBusyMessage("Synchronizing..."); await MachineDataSynchronizer.Synchronize(); NotificationProvider.ReleaseGlobalBusyMessage(); await NotificationProvider.ShowSuccess("Synchronization completed successfully."); } catch (Exception ex) { NotificationProvider.ReleaseGlobalBusyMessage(); await NotificationProvider.ShowError($"Error occurred while trying to synchronize.\n{ex.FlattenMessage()}"); } finally { NotificationProvider.ReleaseGlobalBusyMessage(); IsFree = true; } } } }