using System; using System.Threading.Tasks; using Serilog; using ShareeBike.Model.Connector; using ShareeBike.Model.Device; using ShareeBike.Model.State; using ShareeBike.Model.User; using ShareeBike.MultilingualResources; using ShareeBike.Repository.Exception; using ShareeBike.Services.CopriApi.Exception; using ShareeBike.View; using BikeInfoMutable = ShareeBike.Model.Bikes.BikeInfoNS.BC.BikeInfoMutable; namespace ShareeBike.ViewModel.Bikes.Bike.BC.RequestHandler { /// Provides info about the smart device (phone, tablet, ...) /// View model to be used for progress report and unlocking/ locking view. public class Disposable : Base, IRequestHandler { public Disposable( BikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) : base(selectedBike, selectedBike.State.Value.GetActionText(), true, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) { } /// Request bike. public async Task HandleRequest() { // Lock list to avoid multiple taps while copri action is pending. BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; BikesViewModel.IsIdle = false; var l_oResult = await ViewService.DisplayAlert( string.Empty, string.Format( AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), SelectedBike.TariffDescription?.MaxReservationTimeSpan.TotalMinutes ?? 0), AppResources.MessageAnswerYes, AppResources.MessageAnswerNo); if (l_oResult == false) { // User aborted booking process Log.ForContext().Information("User selected centered bike {l_oId} in order to reserve but action was canceled.", SelectedBike.Id); BikesViewModel.IsIdle = true; return this; } BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; // Stop polling before requesting bike. await ViewUpdateManager().StopAsync(); IsConnected = IsConnectedDelegate(); try { await ConnectorFactory(IsConnected).Command.DoReserve(SelectedBike); } catch (Exception exception) { if (exception is BookingDeclinedException) { // Too many bikes booked. Log.ForContext().Information("Request declined because maximum count of bikes {l_oException.MaxBikesCount} already requested/ booked.", (exception as BookingDeclinedException).MaxBikesCount); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( AppResources.MessageHintTitle, string.Format(AppResources.ErrorReservingBikeTooManyReservationsRentals, SelectedBike.Id, (exception as BookingDeclinedException).MaxBikesCount), AppResources.MessageAnswerOk); } else if (exception is WebConnectFailureException || exception is RequestNotCachableException) { // Copri server is not reachable. Log.ForContext().Information("User selected centered bike {l_oId} but reserving failed (Copri server not reachable).", SelectedBike.Id); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( AppResources.ErrorNoConnectionTitle, AppResources.ErrorNoWeb, AppResources.MessageAnswerOk); } else { Log.ForContext().Error("User selected centered bike {l_oId} but reserving failed. {@l_oException}", SelectedBike.Id, exception); BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert(AppResources.ErrorReservingBikeTitle, exception.Message, AppResources.MessageAnswerOk); } BikesViewModel.ActionText = string.Empty; // Todo: Remove this statement because in catch block ActionText is already set to empty above. BikesViewModel.IsIdle = true; return this; } finally { // Restart polling again. await ViewUpdateManager().StartAsync(); // Update status text and unlock list of bikes because no more action is pending. BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block ActionText is already set to empty. BikesViewModel.IsIdle = true; } Log.ForContext().Information("User reserved bike {l_oId} successfully.", SelectedBike.Id); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } } }