using System; using System.Threading.Tasks; using Serilog; using TINK.Model.Bikes.BikeInfoNS.CopriLock; using TINK.Model.Connector; using TINK.Model.Device; using TINK.Model.User; using TINK.MultilingualResources; using TINK.Repository.Exception; using TINK.View; namespace TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler { using IRequestHandler = BluetoothLock.IRequestHandler; public class BookedOpen : Base, IRequestHandler { /// Provides info about the smart device (phone, tablet, ...) /// View model to be used for progress report and unlocking/ locking view. public BookedOpen( IBikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) : base( selectedBike, nameof(BookedOpen), false, // Lock can only be closed manually and returning is performed by placing bike into the station. isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) { LockitButtonText = AppResources.ActionOpenAndPause; // Lock is open but show button anyway to be less prone to errors. IsLockitButtonVisible = true; } /// Close lock and return bike. public async Task HandleRequestOption1() => await UnsupportedRequest(); /// Close lock in order to pause ride and update COPRI lock state. public async Task HandleRequestOption2() => await OpenLock(); /// Requst 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); } /// Open bike. public async Task OpenLock() { // Unlock bike. Log.ForContext().Information("User request to unlock bike {bike}. For locking state {state} this request is unexpected.", SelectedBike, SelectedBike?.LockInfo?.State); // Stop polling before returning bike. BikesViewModel.IsIdle = false; BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StopUpdatePeridically(); BikesViewModel.ActionText = AppResources.ActivityTextOpeningLock; IsConnected = IsConnectedDelegate(); try { await ConnectorFactory(IsConnected).Command.OpenLockAsync(SelectedBike); } catch (Exception exception) { BikesViewModel.ActionText = string.Empty; if (exception is WebConnectFailureException) { // Copri server is not reachable. Log.ForContext().Information("User selected bike {id} but opening lock failed (Copri server not reachable).", SelectedBike.Id); await ViewService.DisplayAdvancedAlert( AppResources.MessageOpeningLockErrorConnectionTitle, WebConnectFailureException.GetHintToPossibleExceptionsReasons, exception.Message, AppResources.MessageAnswerOk); } else { Log.ForContext().Error("Lock can not be opened. {Exception}", exception); await ViewService.DisplayAlert( AppResources.ErrorOpenLockTitle, exception.Message, AppResources.MessageAnswerOk); } BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartUpdateAyncPeridically(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } Log.ForContext().Information("User paused ride using {bike} successfully.", SelectedBike); BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartUpdateAyncPeridically(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } } }