using System;
using System.Threading.Tasks;
using ShareeBike.Model.Connector;
using ShareeBike.Repository.Request;
using ShareeBike.Services.BluetoothLock;
using ShareeBike.Services.Geolocation;
using ShareeBike.ViewModel;
using static ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.ConnectAndGetStateCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.OpenCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock.Command.DisconnectCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.StartReservationCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.CancelReservationCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.AuthCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.StartRentalCommand;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.EndRentalCommand;
namespace ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock
{
public class BikeInfoMutable : BC.BikeInfoMutable, IBikeInfoMutable
{
/// Provides a connector object.
private Func ConnectorFactory { get; }
/// Provides geolocation information.
private IGeolocationService GeolocationService { get; }
/// Provides geolocation for end rental.
private LocationDto EndRentalLocation { get; }
/// Provides a connector object.
private ILocksService LockService { get; }
/// Delegate to retrieve connected state.
private Func IsConnectedDelegate { get; }
/// Object to manage update of view model objects from Copri.
protected Func ViewUpdateManager { get; }
/// Constructs a bike object from source.
/// Manages update of view model objects from Copri.
public BikeInfoMutable(
IGeolocationService geolocation,
ILocksService lockService,
Func isConnectedDelegate,
Func connectorFactory,
Func viewUpdateManager,
BikeInfo bike,
string stationName) : base(
bike != null
? bike.Bike
: throw new ArgumentNullException(nameof(bike)),
bike.Drive,
bike.DataSource,
bike.IsDemo,
bike.Group,
bike.StationId,
stationName,
bike.OperatorUri,
bike.TariffDescription,
() => DateTime.Now,
bike.State)
{
LockInfo = new LockInfoMutable(
bike.LockInfo.Id,
bike.LockInfo.Guid,
bike.LockInfo.UserKey,
bike.LockInfo.AdminKey,
bike.LockInfo.Seed,
bike.LockInfo.State);
GeolocationService = geolocation
?? throw new ArgumentException($"Can not instantiate {nameof(BikeInfoMutable)}- object. No geolocation object available.");
LockService = lockService
?? throw new ArgumentException($"Can not instantiate {nameof(BikeInfoMutable)}- object. No lock service object available.");
IsConnectedDelegate = isConnectedDelegate
?? throw new ArgumentException($"Can not instantiate {nameof(BikeInfoMutable)}- object. No is connected delegate available.");
ConnectorFactory = connectorFactory
?? throw new ArgumentException($"Can not instantiate {nameof(BikeInfoMutable)}- object. No connector available.");
ViewUpdateManager = viewUpdateManager
?? throw new ArgumentException($"Can not instantiate {nameof(BikeInfoMutable)}- object. No update manger available.");
}
public LockInfoMutable LockInfo { get; }
ILockInfoMutable IBikeInfoMutable.LockInfo => LockInfo;
///
/// Connects the lock.
///
/// View model to process closing notifications.
public async Task ConnectAsync(
IConnectAndGetStateCommandListener listener)
{
await InvokeAsync(
this,
LockService,
listener);
}
///
/// Opens the lock and updates copri.
///
/// View model to process closing notifications.
/// Task which stops polling.
public async Task OpenLockAsync(
IOpenCommandListener listener,
Task stopPollingTask)
{
await InvokeAsync(
this,
LockService,
IsConnectedDelegate,
ConnectorFactory,
listener,
stopPollingTask);
}
///
/// Closes the lock and updates copri.
///
/// View model to process closing notifications.
/// Task which stops polling.
public async Task CloseLockAsync(
ICloseCommandListener listener,
Task stopPollingTask)
{
await InvokeAsync(
this,
GeolocationService,
LockService,
IsConnectedDelegate,
ConnectorFactory,
listener,
stopPollingTask);
}
///
/// Disconnects the lock.
///
/// View model to process closing notifications.
public async Task DisconnectAsync(
IDisconnectCommandListener listener)
{
await InvokeAsync(
this,
LockService,
listener);
}
///
/// Reserves the bike.
///
/// View model to process notifications.
///
public async Task ReserveBikeAsync(
IStartReservationCommandListener listener)
{
await InvokeAsync(
this,
IsConnectedDelegate,
ConnectorFactory,
listener);
}
///
/// Cancels the reservation.
///
/// View model to process notifications.
///
public async Task CancelReservationAsync(
ICancelReservationCommandListener listener)
{
await InvokeAsync(
this,
IsConnectedDelegate,
ConnectorFactory,
listener);
}
///
/// Authenticates the user.
///
/// View model to process notifications.
///
public async Task AuthAsync(
IAuthCommandListener listener)
{
await InvokeAsync(
this,
IsConnectedDelegate,
ConnectorFactory,
listener);
}
///
/// Rents the bike.
///
/// View model to process notifications.
///
public async Task RentBikeAsync(
IStartRentalCommandListener listener)
{
await InvokeAsync(
this,
IsConnectedDelegate,
ConnectorFactory,
listener);
}
///
/// Returns the bike.
///
/// View model to process notifications.
///
public async Task ReturnBikeAsync(
IEndRentalCommandListener listener)
{
var bookingFinished = await InvokeAsync(
this,
GeolocationService,
LockService,
() => DateTime.Now,
IsConnectedDelegate,
ConnectorFactory,
listener);
return bookingFinished;
}
public override string ToString()
{
return $"Id={Id}{(TypeOfBike != null ? $";type={TypeOfBike}" : "")};state={State.ToString()};Lock id={LockInfo.Id}";
}
}
}