sharee.bike-App/SharedBusinessLogic/ViewModel/Bikes/Bike/BluetoothLock/ConnectLockActionViewModel.cs

241 lines
8 KiB
C#
Raw Normal View History

2024-04-09 12:53:23 +02:00
using System;
using System.Threading.Tasks;
using ShareeBike.Model.Connector;
using ShareeBike.MultilingualResources;
using ShareeBike.View;
using Serilog;
using ConnectAndGetStateCommand = ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.ConnectAndGetStateCommand;
using AuthCommand = ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.AuthCommand;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
namespace ShareeBike.ViewModel.Bikes.Bike
{
/// <summary>
/// Return bike action.
/// </summary>
/// <typeparam name="T">Type of owner.</typeparam>
public class ConnectLockActionViewModel<T> :
AuthCommand.IAuthCommandListener,
ConnectAndGetStateCommand.IConnectAndGetStateCommandListener
{
/// <summary>
/// View model to be used for progress report and unlocking/ locking view.
/// </summary>
private IBikesViewModel BikesViewModel { get; set; }
/// <summary>
/// View service to show modal notifications.
/// </summary>
private IViewService ViewService { get; }
/// <summary>Object to start or stop update of view model objects from Copri.</summary>
private Func<IPollingUpdateTaskManager> ViewUpdateManager { get; }
/// <summary> Bike </summary>
private IBikeInfoMutable SelectedBike { get; set; }
/// <summary> Provides a connector object.</summary>
protected Func<bool, IConnector> ConnectorFactory { get; }
/// <summary>
/// Constructs the object.
/// </summary>
/// <param name="selectedBike">Bike to close.</param>
/// <param name="viewUpdateManager">Object to start or stop update of view model objects from Copri.</param>
/// <param name="viewService">View service to show modal notifications.</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
/// <exception cref="ArgumentException"></exception>
public ConnectLockActionViewModel(
IBikeInfoMutable selectedBike,
Func<IPollingUpdateTaskManager> viewUpdateManager,
IViewService viewService,
IBikesViewModel bikesViewModel)
{
SelectedBike = selectedBike;
ViewUpdateManager = viewUpdateManager;
ViewService = viewService;
BikesViewModel = bikesViewModel
?? throw new ArgumentException($"Can not construct {typeof(EndRentalActionViewModel<T>)}-object. {nameof(bikesViewModel)} must not be null.");
}
/// <summary>
/// Processes the start reservation progress.
/// </summary>
/// <param name="step">Current step to process.</param>
public void ReportStep(AuthCommand.Step step)
{
switch (step)
{
case AuthCommand.Step.Authenticate:
BikesViewModel.RentalProcess.StepInfoText = AppResources.MarkingRentalProcessRequestBikeFirstStepAuthenticateInfo;
BikesViewModel.ActionText = AppResources.ActivityTextAuthenticate;
break;
}
}
/// <summary>
/// Processes the authentication state.
/// </summary>
/// <param name="state">State to process.</param>
/// <param name="details">Textual details describing current state.</param>
public async Task ReportStateAsync(AuthCommand.State state, string details)
{
switch (state)
{
case AuthCommand.State.WebConnectFailed:
BikesViewModel.RentalProcess.Result = CurrentStepStatus.Failed;
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAlert(
AppResources.ErrorNoConnectionTitle,
AppResources.ErrorNoWeb,
AppResources.MessageAnswerOk);
break;
case AuthCommand.State.GeneralAuthError:
BikesViewModel.RentalProcess.Result = CurrentStepStatus.Failed;
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAdvancedAlert(
AppResources.ErrorAccountInvalidAuthorization,
details,
AppResources.ErrorTryAgain,
AppResources.MessageAnswerOk);
break;
}
}
/// <summary>
/// Processes the connect to lock progress.
/// </summary>
/// <param name="step">Current step to process.</param>
public void ReportStep(ConnectAndGetStateCommand.Step step)
{
switch (step)
{
case ConnectAndGetStateCommand.Step.ConnectLock:
BikesViewModel.RentalProcess.StepInfoText = AppResources.MarkingRentalProcessRequestBikeFirstStepConnect;
BikesViewModel.ActionText = AppResources.ActivityTextSearchingLock;
break;
case ConnectAndGetStateCommand.Step.GetLockingState:
break;
}
}
/// <summary>
/// Processes the connect to lock state.
/// </summary>
/// <param name="state">State to process.</param>
/// <param name="details">Textual details describing current state.</param>
public async Task ReportStateAsync(ConnectAndGetStateCommand.State state, string details)
{
switch (state)
{
case ConnectAndGetStateCommand.State.OutOfReachError:
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAlert(
AppResources.ErrorConnectLockTitle,
AppResources.ErrorLockOutOfReach,
AppResources.MessageAnswerOk);
break;
case ConnectAndGetStateCommand.State.BluetoothOff:
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAlert(
AppResources.ErrorConnectLockTitle,
AppResources.ErrorLockBluetoothNotOn,
AppResources.MessageAnswerOk);
break;
case ConnectAndGetStateCommand.State.NoLocationPermission:
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAlert(
AppResources.ErrorConnectLockTitle,
AppResources.ErrorNoLocationPermission,
AppResources.MessageAnswerOk);
break;
case ConnectAndGetStateCommand.State.LocationServicesOff:
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAlert(
AppResources.ErrorConnectLockTitle,
AppResources.ErrorLockLocationOff,
AppResources.MessageAnswerOk);
break;
case ConnectAndGetStateCommand.State.GeneralConnectLockError:
BikesViewModel.ActionText = string.Empty;
await ViewService.DisplayAdvancedAlert(
AppResources.ErrorConnectLockTitle,
details,
AppResources.ErrorTryAgain,
AppResources.MessageAnswerOk);
break;
}
}
/// <summary> Search and connect to lock. </summary>
public async Task ConnectLockAsync()
{
Log.ForContext<T>().Information("User request to end rental of bike {bikeId}.", SelectedBike.Id);
// lock GUI
BikesViewModel.IsIdle = false;
// Stop Updater
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
await ViewUpdateManager().StopAsync();
// 1a.Step: Authenticate
try
{
#if USELOCALINSTANCE
var command = new AuthCommand(SelectedBike, ConnectorFactory, ViewUpdateManager);
await command.Invoke(this);
#else
await SelectedBike.AuthAsync(this);
#endif
Log.ForContext<T>().Information("User authenticated for bike {bikeId} successfully.", SelectedBike.Id);
}
catch (Exception exception)
{
Log.ForContext<T>().Information("User could not be authenticated for bike {bikeId}. {@exception}", SelectedBike.Id, exception);
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
await ViewUpdateManager().StartAsync();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
}
// 1b.Step: Get locking state
try
{
#if USELOCALINSTANCE
var command = new ConnectLockAndGetLockingStateCommand(SelectedBike, LockService, ConnectorFactory, ViewUpdateManager);
await command.Invoke(this);
#else
await SelectedBike.ConnectAsync(this);
#endif
Log.ForContext<T>().Information("Lock of {bikeId} connected successfully.", SelectedBike.Id);
}
catch (Exception exception)
{
Log.ForContext<T>().Information("Lock of bike {bikeId} could not be connected. {@exception}", SelectedBike.Id, exception);
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
await ViewUpdateManager().StartAsync();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
}
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
await ViewUpdateManager().StartAsync();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return;
}
}
}