using System;
using System.Threading.Tasks;
using Serilog;
using ShareeBike.Repository.Exception;
using ShareeBike.Model.Connector;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Services.CopriApi.Exception;
using ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
namespace ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command
{
public static class CancelReservationCommand
{
///
/// Possible steps of returning a bike.
///
public enum Step
{
CancelReservation,
}
///
/// Possible steps of returning a bike.
///
public enum State
{
WebConnectFailed,
InvalidResponse,
GeneralCancelReservationError,
}
///
/// Interface to notify view model about steps/ state changes of returning bike process.
///
public interface ICancelReservationCommandListener
{
///
/// Reports current step.
///
/// Current step to report.
void ReportStep(Step currentStep);
///
/// Reports current state.
///
/// Current state to report.
/// Message describing the current state.
///
Task ReportStateAsync(State currentState, string message);
}
///
/// Get current location.
///
///
///
///
public static async Task InvokeAsync(
IBikeInfoMutable bike,
Func isConnectedDelegate,
Func connectorFactory,
ICancelReservationCommandListener listener)
{
// Invokes member to notify about step being started.
void InvokeCurrentStep(Step step)
{
if (listener == null)
return;
try
{
listener.ReportStep(step);
}
catch (Exception exception)
{
Log.ForContext().Error("An exception {@exception} was thrown invoking step-action for step {step} ", exception, step);
}
}
// Invokes member to notify about state change.
async Task InvokeCurrentStateAsync(State state, string message)
{
if (listener == null)
return;
try
{
await listener.ReportStateAsync(state, message);
}
catch (Exception exception)
{
Log.ForContext().Error("An exception {@exception} was thrown invoking state-action for state {state} ", exception, state);
}
}
//// Start Action
// Cancel Reservation
InvokeCurrentStep(Step.CancelReservation);
try
{
await connectorFactory(true).Command.DoCancelReservation(bike);
Log.ForContext().Information("User canceled reservation of bike {bikeId} successfully.", bike.Id);
}
catch (Exception exception)
{
Log.ForContext().Information("User selected reserved bike {bikeId} but cancel reservation failed.", bike.Id);
if (exception is InvalidAuthorizationResponseException)
{
// Copri response is invalid.
Log.ForContext().Error("Invalid auth. response.");
await InvokeCurrentStateAsync(State.InvalidResponse, exception.Message);
}
else if (exception is WebConnectFailureException
|| exception is RequestNotCachableException)
{
// Copri server is not reachable.
Log.ForContext().Error("Copri server not reachable.");
await InvokeCurrentStateAsync(State.WebConnectFailed, exception.Message);
}
else
{
Log.ForContext().Error("{@exception}", exception);
await InvokeCurrentStateAsync(State.GeneralCancelReservationError, exception.Message);
}
throw;
}
}
}
}