using System; using System.Threading.Tasks; using Serilog; using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock; using ShareeBike.Model.Connector; using ShareeBike.Model.Device; using ShareeBike.Model.User; using ShareeBike.MultilingualResources; using ShareeBike.Services.BluetoothLock; using ShareeBike.Services.Geolocation; using ShareeBike.View; using CloseCommand = ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand; using static ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.RequestHandlerFactory; using ShareeBike.Services.BluetoothLock.Exception; namespace ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler { public class BookedOpen : Base, IRequestHandler, CloseCommand.ICloseCommandListener { /// View model to be used for progress report and unlocking/ locking view. public BookedOpen( IBikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, IGeolocationService geolocation, ILocksService lockService, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) : base( selectedBike, AppResources.ActionCloseLock, // Close Lock true, // Show button isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) { LockitButtonText = activeUser.DebugLevel.HasFlag(Model.User.Account.Permissions.ManageAlarmAndSounds) ? AppResources.ActionLockSettings : GetType().Name; IsLockitButtonVisible = activeUser.DebugLevel.HasFlag(Model.User.Account.Permissions.ManageAlarmAndSounds); _closeLockActionViewModel = new CloseLockActionViewModel( selectedBike, viewUpdateManager, viewService, bikesViewModel); } /// /// Holds the view model for close action. /// private readonly CloseLockActionViewModel _closeLockActionViewModel; /// /// Processes the close lock progress. /// /// /// Only used for testing. /// /// Current step to process. public void ReportStep(CloseCommand.Step step) => _closeLockActionViewModel?.ReportStep(step); /// /// Processes the close lock state. /// /// /// Only used for testing. /// /// State to process. /// Textual details describing current state. public async Task ReportStateAsync(CloseCommand.State state, string details) => await _closeLockActionViewModel.ReportStateAsync(state, details); /// Close lock (and return bike). public async Task HandleRequestOption1() { await _closeLockActionViewModel.CloseLockAsync(); if(_closeLockActionViewModel.IsEndRentalRequested == false) { return Create( SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } var _endRentalActionViewModel = new EndRentalActionViewModel( SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, ViewService, BikesViewModel); await _endRentalActionViewModel.EndRentalAsync(); return Create( SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } public async Task HandleRequestOption2() { if (ActiveUser.DebugLevel.HasFlag(Model.User.Account.Permissions.ManageAlarmAndSounds)) { await ManageLockSettings(); } else { throw new InvalidOperationException(); } return Create( SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } /// Manage sound/ alarm settings. /// public async Task ManageLockSettings() { // Stop polling before requesting bike. BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StopAsync(); // Go to lock settings Log.ForContext().Information("User selected bike {bikeId} in order to manage sound/ alarm settings.", SelectedBike.Id); // Alarm settings var resultAlarm = await ViewService.DisplayAlert( "Alarm einstellen", "Alarm auf Einstellung 'niedrige Sensitivität' setzen oder Alarm ausschalten?", "Auf niedrige Sensitivität", "Alarm aus"); try { if (resultAlarm == true) { // Lower alarm sensitivity. BikesViewModel.ActionText = "Setzen Alarm-Einstellungen..."; await LockService[SelectedBike.LockInfo.Id].SetAlarmSettingsAsync(AlarmSettings.SmallSensivitySilent); } else { // Switch off alarm. BikesViewModel.ActionText = "Alarm ausschalten..."; await LockService[SelectedBike.LockInfo.Id].SetIsAlarmOffAsync(true); } } catch (OutOfReachException exception) { Log.ForContext().Debug("Can not set alarm settings. {Exception}", exception); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( "Fehler beim Setzen der Alarm-Einstellungen!", "Alarm kann erst eingestellt werden, wenn Rad in der Nähe ist.", AppResources.MessageAnswerOk); return this; } catch (Exception exception) { Log.ForContext().Error("Can not set alarm settings. {Exception}", exception); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( "Fehler beim Setzen der Alarms-Einstellungen!", exception.Message, AppResources.MessageAnswerOk); return this; } // Sound settings var resultSound = await ViewService.DisplayAlert( "Sounds einstellen", "Sounds auf Einstellung 'Warnung' setzen oder alle Sounds ausschalten?", "Auf Warnung", "Alles aus"); try { if (resultSound == true) { BikesViewModel.ActionText = "Sounds einstellen auf 'Warnung'..."; await LockService[SelectedBike.LockInfo.Id].SetSoundAsync(SoundSettings.Warn); } else { BikesViewModel.ActionText = "Alle Sounds ausschalten..."; await LockService[SelectedBike.LockInfo.Id].SetSoundAsync(SoundSettings.AllOff); } } catch (OutOfReachException exception) { Log.ForContext().Debug("Can not set sounds. {Exception}", exception); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( "Fehler beim Einstellen der Sounds!", "Sounds können erst eingestellt werden, wenn Rad in der Nähe ist.", AppResources.MessageAnswerOk); return this; } catch (Exception exception) { Log.ForContext().Error("Can not set sounds. {Exception}", exception); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( "Fehler beim Einstellen der Sounds!", exception.Message, AppResources.MessageAnswerOk); return Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartAsync(); // Restart polling again. BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; // Unlock GUI return this; } /// Request is not supported, button should be disabled. /// public async Task UnsupportedRequest() { Log.ForContext().Error("Click of unsupported button click detected."); return await Task.FromResult(this); } } }