2022-10-26 20:53:18 +02:00
using System ;
2021-05-13 20:03:07 +02:00
using System.Threading.Tasks ;
2022-08-30 15:42:25 +02:00
using Serilog ;
2021-05-13 20:03:07 +02:00
using TINK.Model.Connector ;
2022-08-30 15:42:25 +02:00
using TINK.Model.Device ;
2021-05-13 20:03:07 +02:00
using TINK.Model.User ;
using TINK.MultilingualResources ;
2022-08-30 15:42:25 +02:00
using TINK.Repository.Exception ;
2022-10-26 20:53:18 +02:00
using TINK.Services.CopriApi.Exception ;
2021-05-13 20:03:07 +02:00
using TINK.View ;
2022-08-30 15:42:25 +02:00
using BikeInfoMutable = TINK . Model . Bikes . BikeInfoNS . BC . BikeInfoMutable ;
2021-05-13 20:03:07 +02:00
namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
{
2022-09-06 16:08:19 +02:00
public class Reserved : Base < BikeInfoMutable > , IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public Reserved (
BikeInfoMutable selectedBike ,
Func < bool > isConnectedDelegate ,
Func < bool , IConnector > connectorFactory ,
Func < IPollingUpdateTaskManager > viewUpdateManager ,
ISmartDevice smartDevice ,
IViewService viewService ,
IBikesViewModel bikesViewModel ,
IUser activeUser ) : base ( selectedBike , AppResources . ActionCancelRequest , true , isConnectedDelegate , connectorFactory , viewUpdateManager , smartDevice , viewService , bikesViewModel , activeUser )
{
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Executes user request to cancel reservation. </summary>
public async Task < IRequestHandler > HandleRequest ( )
{
// Lock list to avoid multiple taps while copri action is pending.
BikesViewModel . ActionText = AppResources . ActivityTextOneMomentPlease ;
BikesViewModel . IsIdle = false ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
BikesViewModel . ActionText = string . Empty ;
var l_oResult = await ViewService . DisplayAlert (
string . Empty ,
string . Format ( "Reservierung für Fahrrad {0} aufheben?" , SelectedBike . GetFullDisplayName ( ) ) ,
"Ja" ,
"Nein" ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
if ( l_oResult = = false )
{
// User aborted cancel process
Log . ForContext < Reserved > ( ) . Information ( "User selected reserved bike {l_oId} in order to cancel reservation but action was canceled." , SelectedBike . Id ) ;
BikesViewModel . IsIdle = true ;
return this ;
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
BikesViewModel . ActionText = AppResources . ActivityTextOneMomentPlease ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// Stop polling before cancel request.
await ViewUpdateManager ( ) . StopUpdatePeridically ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
try
{
IsConnected = IsConnectedDelegate ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
await ConnectorFactory ( IsConnected ) . Command . DoCancelReservation ( SelectedBike ) ;
2021-05-13 20:03:07 +02:00
2023-04-19 12:14:14 +02:00
// If canceling bike succeeds remove bike because it is not ready to be booked again
2022-09-06 16:08:19 +02:00
IsRemoveBikeRequired = true ;
}
2022-10-26 20:53:18 +02:00
catch ( Exception exception )
2022-09-06 16:08:19 +02:00
{
2022-10-26 20:53:18 +02:00
if ( exception is InvalidAuthorizationResponseException )
2022-09-06 16:08:19 +02:00
{
// Copri response is invalid.
Log . ForContext < Reserved > ( ) . Error ( "User selected reserved bike {l_oId} but canceling reservation failed (Invalid auth. response)." , SelectedBike . Id ) ;
BikesViewModel . ActionText = String . Empty ;
2022-10-26 20:53:18 +02:00
await ViewService . DisplayAlert ( "Fehler beim Stornieren der Buchung!" , exception . Message , "OK" ) ;
2022-09-06 16:08:19 +02:00
BikesViewModel . IsIdle = true ;
return this ;
}
2022-10-26 20:53:18 +02:00
else if ( exception is WebConnectFailureException
| | exception is RequestNotCachableException )
2022-09-06 16:08:19 +02:00
{
// Copri server is not reachable.
Log . ForContext < Reserved > ( ) . Information ( "User selected reserved bike {l_oId} but cancel reservation failed (Copri server not reachable)." , SelectedBike . Id ) ;
BikesViewModel . ActionText = String . Empty ;
await ViewService . DisplayAlert (
"Verbingungsfehler beim Stornieren der Buchung!" ,
2022-10-26 20:53:18 +02:00
string . Format ( "{0}\r\n{1}" , exception . Message , WebConnectFailureException . GetHintToPossibleExceptionsReasons ) ,
2022-09-06 16:08:19 +02:00
"OK" ) ;
BikesViewModel . IsIdle = true ;
return this ;
}
else
{
2022-10-26 20:53:18 +02:00
Log . ForContext < Reserved > ( ) . Error ( "User selected reserved bike {l_oId} but cancel reservation failed. {@l_oException}." , SelectedBike . Id , exception ) ;
2022-09-06 16:08:19 +02:00
BikesViewModel . ActionText = String . Empty ;
2022-10-26 20:53:18 +02:00
await ViewService . DisplayAlert ( "Fehler beim Stornieren der Buchung!" , exception . Message , "OK" ) ;
2022-09-06 16:08:19 +02:00
BikesViewModel . IsIdle = true ;
return this ;
}
}
finally
{
// Restart polling again.
await ViewUpdateManager ( ) . StartUpdateAyncPeridically ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// 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.
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
Log . ForContext < Reserved > ( ) . Information ( "User canceled reservation of bike {l_oId} successfully." , SelectedBike . Id ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
BikesViewModel . IsIdle = true ;
return RequestHandlerFactory . Create ( SelectedBike , IsConnectedDelegate , ConnectorFactory , ViewUpdateManager , SmartDevice , ViewService , BikesViewModel , ActiveUser ) ;
}
}
2021-05-13 20:03:07 +02:00
}