using System; using Serilog; using System.Threading.Tasks; using TINK.Model.Connector; using TINK.Model.State; using TINK.View; using TINK.Repository.Exception; using TINK.Services.Geolocation; using TINK.MultilingualResources; using TINK.Model.Bikes.Bike.CopriLock; using TINK.Model.User; using TINK.Model.Device; namespace TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler { using IRequestHandler = BluetoothLock.IRequestHandler; public class DisposableClosed : Base, IRequestHandler { /// Provides info about the smart device (phone, tablet, ...). /// View model to be used for progress report and unlocking/ locking view. public DisposableClosed( IBikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, IGeolocation geolocation, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) : base( selectedBike, AppResources.ActionOpenAndBook, // Button text: "Schloss öffnen & Rad mieten" true, // Show copri button to enable reserving and opening isConnectedDelegate, connectorFactory, geolocation, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) { LockitButtonText = GetType().Name; IsLockitButtonVisible = false; // If bike is not reserved/ booked app can not connect to lock } /// Gets the bike state. public override InUseStateEnum State => InUseStateEnum.Disposable; /// Reserve bike and connect to lock. public async Task HandleRequestOption1() => await BookAndOpen(); public async Task HandleRequestOption2() => await UnsupportedRequest(); /// Reserve bike and connect to lock. public async Task BookAndOpen() { BikesViewModel.IsIdle = false; // Ask whether to really book bike? var alertResult = await ViewService.DisplayAlert( string.Empty, string.Format(AppResources.QuestionOpenLockAndBookBike, SelectedBike.GetFullDisplayName()), AppResources.MessageAnswerYes, AppResources.MessageAnswerNo); if (alertResult == false) { // User aborted booking process Log.ForContext().Information("User selected recently requested bike {bike} in order to reserve but did deny to book bike.", SelectedBike); // Restart polling again. BikesViewModel.IsIdle = true; return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } Log.ForContext().Information("User selected recently requested bike {bike} in order to book.", SelectedBike); // Book bike prior to opening lock. BikesViewModel.ActionText = AppResources.ActivityTextRentingBike; IsConnected = IsConnectedDelegate(); try { await ConnectorFactory(IsConnected).Command.BookAndOpenAync(SelectedBike); } catch (Exception l_oException) { BikesViewModel.ActionText = string.Empty; if (l_oException is WebConnectFailureException) { // Copri server is not reachable. Log.ForContext().Information("User selected recently requested bike {l_oId} but booking failed (Copri server not reachable).", SelectedBike.Id); await ViewService.DisplayAdvancedAlert( AppResources.MessageRentingBikeErrorConnectionTitle, WebConnectFailureException.GetHintToPossibleExceptionsReasons, l_oException.Message, AppResources.MessageAnswerOk); } else { Log.ForContext().Error("User selected recently requested bike {l_oId} but reserving failed. {@l_oException}", SelectedBike.Id, l_oException); await ViewService.DisplayAdvancedAlert( AppResources.MessageRentingBikeErrorGeneralTitle, string.Empty, l_oException.Message, AppResources.MessageAnswerOk); } BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. BikesViewModel.IsIdle = true; // Unlock GUI return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } Log.ForContext().Information("User reserved bike {bike} successfully.", SelectedBike); BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; // Unlock GUI return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } /// 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); } } }