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