using System; using System.Threading.Tasks; using ShareeBike.Model.Connector; using ShareeBike.MultilingualResources; using ShareeBike.View; using Serilog; using CancelReservationCommand = ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.CancelReservationCommand; using DisconnectCommand = ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.DisconnectCommand; using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock; namespace ShareeBike.ViewModel.Bikes.Bike { /// /// Return bike action. /// /// Type of owner. public class CancelReservationActionViewModel : CancelReservationCommand.ICancelReservationCommandListener, DisconnectCommand.IDisconnectCommandListener { /// /// View model to be used for progress report and unlocking/ locking view. /// private IBikesViewModel BikesViewModel { get; set; } /// /// View service to show modal notifications. /// private IViewService ViewService { get; } /// Object to start or stop update of view model objects from Copri. private Func ViewUpdateManager { get; } /// Bike close. private IBikeInfoMutable SelectedBike { get; } /// Provides a connector object. protected Func ConnectorFactory { get; } /// /// Constructs the object. /// /// Bike to close. /// Object to start or stop update of view model objects from Copri. /// View service to show modal notifications. /// View model to be used for progress report and unlocking/ locking view. /// public CancelReservationActionViewModel( IBikeInfoMutable selectedBike, Func viewUpdateManager, IViewService viewService, IBikesViewModel bikesViewModel) { SelectedBike = selectedBike; ViewUpdateManager = viewUpdateManager; ViewService = viewService; BikesViewModel = bikesViewModel ?? throw new ArgumentException($"Can not construct {typeof(EndRentalActionViewModel)}-object. {nameof(bikesViewModel)} must not be null."); } /// /// Processes the start reservation progress. /// /// Current step to process. public void ReportStep(CancelReservationCommand.Step step) { switch (step) { case CancelReservationCommand.Step.CancelReservation: BikesViewModel.ActionText = AppResources.ActivityTextCancelingReservation; break; } } /// /// Processes the start reservation state. /// /// State to process. /// Textual details describing current state. public async Task ReportStateAsync(CancelReservationCommand.State state, string details) { switch (state) { case CancelReservationCommand.State.InvalidResponse: BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( AppResources.ErrorCancelReservationTitle, AppResources.ErrorAccountInvalidAuthorization, AppResources.MessageAnswerOk); break; case CancelReservationCommand.State.WebConnectFailed: BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAlert( AppResources.ErrorNoConnectionTitle, AppResources.ErrorNoWeb, AppResources.MessageAnswerOk); break; case CancelReservationCommand.State.GeneralCancelReservationError: BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAdvancedAlert( AppResources.ErrorCancelReservationTitle, details, AppResources.ErrorTryAgain, AppResources.MessageAnswerOk); break; } } /// /// Processes the disconnect from lock progress. /// /// Current step to process. public void ReportStep(DisconnectCommand.Step step) { switch (step) { case DisconnectCommand.Step.DisconnectLock: BikesViewModel.ActionText = AppResources.ActivityTextDisconnectingLock; break; } } /// /// Processes the disconnect from lock state. /// /// State to process. /// Textual details describing current state. public async Task ReportStateAsync(DisconnectCommand.State state, string details) { switch (state) { case DisconnectCommand.State.GeneralDisconnectError: BikesViewModel.ActionText = string.Empty; await ViewService.DisplayAdvancedAlert( AppResources.ErrorAccountInvalidAuthorization, details, AppResources.ErrorTryAgain, AppResources.MessageAnswerOk); break; } } /// Cancel reservation. public async Task CancelReservationAsync() { // lock GUI BikesViewModel.IsIdle = false; BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StopAsync(); // 1.Step: Cancel reservation try { #if USELOCALINSTANCE var command = new CancelReservationCommand(SelectedBike, ConnectorFactory, ViewUpdateManager); await command.Invoke(this); #else await SelectedBike.CancelReservationAsync(this); #endif } catch (Exception exception) { Log.ForContext().Information("Reservation of bike {bikeId} could not be canceled. {@exception}", SelectedBike.Id, exception); BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StartAsync(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return; } // 2. Step: Disconnect Lock if (SelectedBike.LockInfo.State != LockingState.UnknownDisconnected) { try { #if USELOCALINSTANCE var command = new DisconnectCommand(SelectedBike, ConnectorFactory, ViewUpdateManager); await command.Invoke(this); #else await SelectedBike.DisconnectAsync(this); #endif } catch (Exception exception) { Log.ForContext().Information("Lock of bike {bikeId} could not be disconnected. {@exception}", SelectedBike.Id, exception); } } BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; await ViewUpdateManager().StartAsync(); BikesViewModel.ActionText = string.Empty; BikesViewModel.IsIdle = true; return; } } }