using System;
using System.Collections.Generic;
using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.MiniSurvey;
using TINK.Model.State;
using TINK.Repository.Response;
using BikeExtension = TINK.Model.Bikes.BikeInfoNS.BikeNS.BikeExtension;
using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo;
namespace TINK.Model.Connector.Updater
{
///
/// Constructs bike info instances/ bike info derived instances.
///
public static class BikeInfoFactory
{
/// Set default lock type to .
public static LockModel DEFAULTLOCKMODEL = LockModel.Sigo;
/// Creates a bike info object from copri response.
/// Copri response for a disposable bike.
public static BikeInfo Create(BikeInfoAvailable bikeInfo)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
var lockModel = bikeInfo.GetLockModel();
if (lockModel.HasValue
&& lockModel.Value == LockModel.BordComputer)
{
// Manual lock bikes are no more supported.
Log.Error(
$"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. " +
"Manual lock bikes are no more supported." +
$"Bike number: {bikeInfo.bike}{(bikeInfo.station != null ? $"station number {bikeInfo.station}" : string.Empty)}."
);
return null;
}
switch (bikeInfo.GetState())
{
case InUseStateEnum.Disposable:
case InUseStateEnum.FeedbackPending:
break;
default:
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Unexpected state {bikeInfo.GetState()} detected.");
return null;
}
if (string.IsNullOrEmpty(bikeInfo.station))
{
// Bike available must always have a station id because bikes can only be returned at a station.
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. No station info set.");
return null;
}
var lockType = lockModel.HasValue
? BikeExtension.GetLockType(lockModel.Value)
: BikeExtension.GetLockType(DEFAULTLOCKMODEL); // Map bikes without "system"- entry in response to backend- locks.
try
{
switch (lockType)
{
case LockType.Backend:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetState() == InUseStateEnum.FeedbackPending,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription) null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup(),
miniSurvey: bikeInfo.user_miniquery != null
? new MiniSurveyModel(new Dictionary {
{ "q1", new QuestionModel()} // Add a dummy querry. Querries are not yet read from COPRI but compiled into the app.
})
: new MiniSurveyModel(),
co2Saving: bikeInfo.co2saving);
case LockType.Bluethooth:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
bikeInfo.GetBluetoothLockId(),
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
default:
throw new ArgumentException($"Unsupported lock type {lockType} detected.");
}
}
catch (ArgumentException ex)
{
// Contructor reported invalid arguemts (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Invalid response detected. Available bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
}
/// Creates a bike info object from copri response.
/// Copri response.
/// Mail address of user.
/// Date and time provider function.
public static BikeInfo Create(
BikeInfoReservedOrBooked bikeInfo,
string mailAddress,
Func dateTimeProvider)
{
if (bikeInfo == null) throw new ArgumentNullException(nameof(bikeInfo));
var lockModel = bikeInfo.GetLockModel();
if (lockModel.HasValue
&& lockModel.Value == LockModel.BordComputer)
{
// Manual lock bikes are no more supported.
Log.Error(
$"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. " +
"Manual lock bikes are no more supported." +
$"Bike number: {bikeInfo.bike}{(bikeInfo.station != null ? $", station number {bikeInfo.station}" : string.Empty)}."
);
return null;
}
var lockType = lockModel.HasValue
? BikeExtension.GetLockType(lockModel.Value)
: BikeExtension.GetLockType(DEFAULTLOCKMODEL); // Map bikes without "system"- entry in response to backend- locks.
// Check if bike is a bluetooth lock bike.
int lockSerial = bikeInfo.GetBluetoothLockId();
Guid lockGuid = bikeInfo.GetBluetoothLockGuid();
switch (bikeInfo.GetState())
{
case InUseStateEnum.Reserved:
try
{
switch (lockType)
{
case LockType.Bluethooth:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
lockSerial,
lockGuid,
bikeInfo.GetUserKey(),
bikeInfo.GetAdminKey(),
bikeInfo.GetSeed(),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
dateTimeProvider,
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
case LockType.Backend:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
dateTimeProvider,
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
default:
throw new ArgumentException($"Unsupported lock type {lockType} detected.");
}
}
catch (ArgumentException ex)
{
// Contructor reported invalid arguemts (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoReservedOrBooked)} argument. Invalid response detected. Reserved bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
case InUseStateEnum.Booked:
try
{
switch (lockModel)
{
case LockModel.ILockIt:
return new Bikes.BikeInfoNS.BluetoothLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.ILockIt,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
lockSerial,
bikeInfo.GetBluetoothLockGuid(),
bikeInfo.GetUserKey(),
bikeInfo.GetAdminKey(),
bikeInfo.GetSeed(),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
case LockModel.BordComputer:
return new BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.BordComputer,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup(),
bikeInfo.station,
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.timeCode);
default:
return new Bikes.BikeInfoNS.CopriLock.BikeInfo(
new Bike(
bikeInfo.bike,
LockModel.Sigo,
bikeInfo.GetWheelType(),
bikeInfo.GetTypeOfBike(),
bikeInfo.description),
DriveFactory.Create(bikeInfo?.bike_type),
bikeInfo.GetFrom(),
mailAddress,
bikeInfo.station,
new Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = bikeInfo.GetCopriLockingState() }.Build(),
bikeInfo.GetOperatorUri(),
#if !NOTARIFFDESCRIPTION
bikeInfo.rental_description != null
? RentalDescriptionFactory.Create(bikeInfo.rental_description)
: TariffDescriptionFactory.Create(bikeInfo.tariff_description),
#else
Create((TINK.Repository.Response.TariffDescription)null),
#endif
bikeInfo.GetIsDemo(),
bikeInfo.GetGroup());
}
}
catch (ArgumentException ex)
{
// Contructor reported invalid arguemts (missing lock id, ....).
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoReservedOrBooked)} argument. Invalid response detected. Booked bike with id {bikeInfo.bike} skipped. {ex.Message}");
return null;
}
default:
Log.Error($"Can not create new {nameof(BikeInfo)}-object from {nameof(BikeInfoAvailable)} argument. Unexpected state {bikeInfo.GetState()} detected.");
return null;
}
}
}
}