using System; using Serilog; using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock; using ShareeBike.Model.Connector; using ShareeBike.Model.Device; using ShareeBike.Model.User; using ShareeBike.MultilingualResources; using ShareeBike.Services.BluetoothLock; using ShareeBike.Services.Geolocation; using ShareeBike.View; using ShareeBike.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler; namespace ShareeBike.ViewModel.Bikes.Bike.BluetoothLock { public static class RequestHandlerFactory { /// Creates a request handler. /// /// /// /// /// /// Provides info about the smart device (phone, tablet, ...) /// /// View model to be used for progress report and unlocking/ locking view. /// Specifies the context (last action performed). /// Request handler. public static IRequestHandler Create( Model.Bikes.BikeInfoNS.BC.IBikeInfoMutable selectedBike, Func isConnectedDelegate, Func connectorFactory, IGeolocationService geolocation, ILocksService lockService, Func viewUpdateManager, ISmartDevice smartDevice, IViewService viewService, IBikesViewModel bikesViewModel, IUser activeUser) { if (!(selectedBike is IBikeInfoMutable selectedBluetoothLockBike)) return null; switch (selectedBluetoothLockBike.State.Value) { case Model.State.InUseStateEnum.Disposable: // Bike is reserved, select action depending on lock state. switch (selectedBluetoothLockBike.LockInfo.State) { case LockingState.Open: case LockingState.UnknownFromHardwareError: // Unexpected state detected. /// This state is unexpected because /// - app does not allow to return bike/ cancel reservation when lock is closed /// - as long as app is connected to lock /// - lock can not be opened manually /// - no other device can access lock /// Nevertheless this state is not expected let user either /// - close lock or /// - rent bike /// Log.Error("Unexpected state {BookingState}/ {LockingState} detected.", selectedBluetoothLockBike.State.Value, selectedBluetoothLockBike.LockInfo.State); return new DisposableOpen( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.Closed: case LockingState.UnknownDisconnected: // Do not allow interaction with lock before reserving bike. return new DisposableDisconnected( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); default: // Invalid state detected. Lock must never be open if bike is reserved. throw new ArgumentException(); } case Model.State.InUseStateEnum.Reserved: // Bike is reserved, select action depending on lock state. switch (selectedBluetoothLockBike.LockInfo.State) { case LockingState.Closed: // Lock could not be opened after reserving bike. return new ReservedClosed( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.UnknownDisconnected: return new ReservedDisconnected( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.Open: // Unwanted state detected. /// This state might occur when a ILOCKIT was manually opened (color code) and app connects afterwards. Log.Error("Unwanted state {BookingState}/ {LockingState} detected.", selectedBluetoothLockBike.State.Value, selectedBluetoothLockBike.LockInfo.State); return new ReservedOpen( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.UnknownFromHardwareError: // User wants to return bike/ pause ride. return new ReservedUnknown( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); default: // Invalid state detected. Lock must never be open if bike is reserved. throw new ArgumentException(); } case Model.State.InUseStateEnum.Booked: // Bike is booked, select action depending on lock state. switch (selectedBluetoothLockBike.LockInfo.State) { case LockingState.Closed: // User wants to close lock. return new BookedClosed( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.Open: // User wants to return bike/ pause ride. return new BookedOpen( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.UnknownFromHardwareError: // User wants to return bike/ pause ride. return new BookedUnknown( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); case LockingState.UnknownDisconnected: // Invalid state detected. // If bike is booked lock state must be queried before creating view model. return new BookedDisconnected( selectedBluetoothLockBike, isConnectedDelegate, connectorFactory, geolocation, lockService, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser); default: // Invalid state detected. Lock must never be open if bike is reserved. throw new ArgumentException(); } default: // Unexpected copri state detected. Log.Error("Unexpected locking {BookingState}/ {LockingState} detected.", selectedBluetoothLockBike.State.Value, selectedBluetoothLockBike.LockInfo.State); return new InvalidState( bikesViewModel, selectedBluetoothLockBike.State.Value, selectedBluetoothLockBike.LockInfo.State, string.Format(AppResources.MarkingBikeInfoErrorStateUnknownDetected, selectedBluetoothLockBike.Description)); } } } }