using System; using System.Threading.Tasks; using Serilog; using ShareeBike.Model.Bikes.BikeInfoNS.CopriLock; using ShareeBike.Model.Connector; using ShareeBike.Model.Device; using ShareeBike.Model.User; using ShareeBike.MultilingualResources; using ShareeBike.Repository.Exception; using ShareeBike.View; namespace ShareeBike.ViewModel.Bikes.Bike.CopriLock.RequestHandler { using IRequestHandler = BluetoothLock.IRequestHandler; public class FeedbackPending : Base, IRequestHandler { /// Provides info about the smart device (phone, tablet, ...) /// View model to be used for progress report and unlocking/ locking view. public FeedbackPending( IBikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) : base( selectedBike, nameof(FeedbackPending), false, // No other action but give feedback allowed. isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) { LockitButtonText = AppResources.ActionGiveFeedback; IsLockitButtonVisible = true; // Show button to enable opening lock in case user took a pause and does not want to return the bike. } /// Return bike. public async Task HandleRequestOption1() => await UnsupportedRequest(); /// Open bike and update COPRI lock state. public async Task HandleRequestOption2() => await GiveFeedback(); /// 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); } /// Open bike and update COPRI lock state. public async Task GiveFeedback() { BikesViewModel.IsIdle = false; BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StopAsync(); // Do get Feedback var battery = SelectedBike.Drive?.Battery; var feedback = await ViewService.DisplayUserFeedbackPopup( battery); if (battery != null && feedback.CurrentChargeBars != null) { SelectedBike.Drive.Battery.CurrentChargeBars = feedback.CurrentChargeBars; } BikesViewModel.ActionText = AppResources.ActivityTextSubmittingFeedback; IsConnected = IsConnectedDelegate(); try { await ConnectorFactory(IsConnected).Command.DoSubmitFeedback( new UserFeedbackDto { BikeId = SelectedBike.Id, CurrentChargeBars = feedback.CurrentChargeBars, IsBikeBroken = feedback.IsBikeBroken, Message = feedback.Message }, SelectedBike?.OperatorUri); } catch (Exception exception) { BikesViewModel.ActionText = string.Empty; if (exception is ResponseException copriException) { // Copri server is not reachable. Log.ForContext().Information("Submitting feedback for bike {bike} failed. COPRI returned an error.", SelectedBike); } else { Log.ForContext().Error("Submitting feedback for bike {bike} failed. {@Exception}", SelectedBike.Id, exception); } await ViewService.DisplayAlert( AppResources.ErrorSubmitFeedbackTitle, AppResources.ErrorNoWeb, AppResources.MessageAnswerOk); BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartAsync(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } // Feedback was given successfully. // Set state from FeedbackPending to Available. SelectedBike.State.Load(Model.State.InUseStateEnum.Disposable); if (SelectedBike?.BookingFinishedModel?.MiniSurvey?.Questions?.Count > 0) { // No need to restart polling again because different page is shown. await ViewService.PushModalAsync(ViewTypes.MiniSurvey); } BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater; await ViewUpdateManager().StartAsync(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); } } }