2021-05-13 20:03:07 +02:00
using Serilog ;
using System ;
using System.Threading.Tasks ;
using TINK.Model.Connector ;
2021-06-26 20:57:55 +02:00
using TINK.Repository.Exception ;
2021-05-13 20:03:07 +02:00
using TINK.Model.State ;
using TINK.Model.User ;
using TINK.MultilingualResources ;
using TINK.View ;
using BikeInfoMutable = TINK . Model . Bike . BC . BikeInfoMutable ;
2021-06-26 20:57:55 +02:00
using TINK.Model.Device ;
2021-05-13 20:03:07 +02:00
namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
{
2021-06-26 20:57:55 +02:00
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
2021-05-13 20:03:07 +02:00
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public class Disposable : Base < BikeInfoMutable > , IRequestHandler
{
public Disposable (
BikeInfoMutable selectedBike ,
Func < bool > isConnectedDelegate ,
Func < bool , IConnector > connectorFactory ,
Func < IPollingUpdateTaskManager > viewUpdateManager ,
2021-06-26 20:57:55 +02:00
ISmartDevice smartDevice ,
2021-05-13 20:03:07 +02:00
IViewService viewService ,
IBikesViewModel bikesViewModel ,
2021-06-26 20:57:55 +02:00
IUser activeUser ) : base ( selectedBike , selectedBike . State . Value . GetActionText ( ) , true , isConnectedDelegate , connectorFactory , viewUpdateManager , smartDevice , viewService , bikesViewModel , activeUser )
2021-05-13 20:03:07 +02:00
{
}
2021-06-26 20:57:55 +02:00
/// <summary> Gets the bike state. </summary>
2021-05-13 20:03:07 +02:00
public override InUseStateEnum State = > InUseStateEnum . Disposable ;
/// <summary> Request bike. </summary>
public async Task < IRequestHandler > HandleRequest ( )
{
// Lock list to avoid multiple taps while copri action is pending.
BikesViewModel . ActionText = AppResources . ActivityTextOneMomentPlease ;
BikesViewModel . IsIdle = false ;
var l_oResult = await ViewService . DisplayAlert (
string . Empty ,
2021-06-26 20:57:55 +02:00
string . Format ( AppResources . QuestionReserveBike , SelectedBike . GetFullDisplayName ( ) , StateRequestedInfo . MaximumReserveTime . Minutes ) ,
2021-05-13 20:03:07 +02:00
AppResources . MessageAnswerYes ,
AppResources . MessageAnswerNo ) ;
if ( l_oResult = = false )
{
// User aborted booking process
Log . ForContext < Disposable > ( ) . Information ( "User selected availalbe bike {l_oId} in order to reserve but action was canceled." , SelectedBike . Id ) ;
BikesViewModel . IsIdle = true ;
return this ;
}
BikesViewModel . ActionText = AppResources . ActivityTextOneMomentPlease ;
// Stop polling before requesting bike.
await ViewUpdateManager ( ) . StopUpdatePeridically ( ) ;
IsConnected = IsConnectedDelegate ( ) ;
try
{
await ConnectorFactory ( IsConnected ) . Command . DoReserve ( SelectedBike ) ;
}
catch ( Exception l_oException )
{
if ( l_oException is BookingDeclinedException )
{
// Too many bikes booked.
Log . ForContext < Disposable > ( ) . Information ( "Request declined because maximum count of bikes {l_oException.MaxBikesCount} already requested/ booked." , ( l_oException as BookingDeclinedException ) . MaxBikesCount ) ;
BikesViewModel . ActionText = string . Empty ;
await ViewService . DisplayAlert (
AppResources . MessageTitleHint ,
string . Format ( AppResources . MessageReservationBikeErrorTooManyReservationsRentals , SelectedBike . Id , ( l_oException as BookingDeclinedException ) . MaxBikesCount ) ,
AppResources . MessageAnswerOk ) ;
}
else if ( l_oException is WebConnectFailureException )
{
// Copri server is not reachable.
Log . ForContext < Disposable > ( ) . Information ( "User selected availalbe bike {l_oId} but reserving failed (Copri server not reachable)." , SelectedBike . Id ) ;
BikesViewModel . ActionText = string . Empty ;
await ViewService . DisplayAlert (
"Verbingungsfehler beim Reservieren des Rads!" ,
string . Format ( "{0}\r\n{1}" , l_oException . Message , WebConnectFailureException . GetHintToPossibleExceptionsReasons ) ,
"OK" ) ;
}
else
{
Log . ForContext < Disposable > ( ) . Error ( "User selected availalbe bike {l_oId} but reserving failed. {@l_oException}" , SelectedBike . Id , l_oException ) ;
BikesViewModel . ActionText = string . Empty ;
await ViewService . DisplayAlert ( "Fehler beim Reservieren des Rads!" , l_oException . Message , "OK" ) ;
}
BikesViewModel . ActionText = string . Empty ; // Todo: Remove this statement because in catch block ActionText is already set to empty above.
BikesViewModel . IsIdle = true ;
return this ;
}
finally
{
// Restart polling again.
await ViewUpdateManager ( ) . StartUpdateAyncPeridically ( ) ;
// Update status text and unlock list of bikes because no more action is pending.
BikesViewModel . ActionText = string . Empty ; // Todo: Move this statement in front of finally block because in catch block ActionText is already set to empty.
BikesViewModel . IsIdle = true ;
}
Log . ForContext < Disposable > ( ) . Information ( "User reserved bike {l_oId} successfully." , SelectedBike . Id ) ;
2021-06-26 20:57:55 +02:00
return RequestHandlerFactory . Create ( SelectedBike , IsConnectedDelegate , ConnectorFactory , ViewUpdateManager , SmartDevice , ViewService , BikesViewModel , ActiveUser ) ;
2021-05-13 20:03:07 +02:00
}
}
}