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;
}
}
}