using System; using System.Collections.Generic; using Serilog; using TINK.Model.Bikes; using TINK.Model.Bikes.BikeInfoNS.BC; using TINK.Model.State; using TINK.Model.Station; using TINK.Model.Station.Operator; using TINK.Model.User.Account; using TINK.Repository.Exception; using TINK.Repository.Response; using TINK.Services.CopriApi; using Xamarin.Forms; using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo; using IBikeInfoMutable = TINK.Model.Bikes.BikeInfoNS.BC.IBikeInfoMutable; namespace TINK.Model.Connector.Updater { /// /// Connects TINK app to copri using JSON as input data format. /// /// Rename to UpdateFromCopri. public static class UpdaterJSON { /// Loads a bike object from copri server cancel reservation/ booking update request. /// Bike object to load response into. /// Controls whether notify property changed events are fired or not. public static void Load( this IBikeInfoMutable bike, NotifyPropertyChangedLevel notifyLevel) => bike.State.Load(InUseStateEnum.Disposable, notifyLevel: notifyLevel); /// /// Gets all statsion for station provider and add them into station list. /// /// List of stations to update. public static StationDictionary GetStationsAllMutable(this StationsAvailableResponse stationsAllResponse) { // Get stations from Copri/ file/ memory, .... if (stationsAllResponse == null || stationsAllResponse.stations == null) { // Latest list of stations could not be retrieved from provider. return new StationDictionary(); } Version.TryParse(stationsAllResponse.copri_version, out Version copriVersion); var stations = new StationDictionary(p_oVersion: copriVersion); foreach (var station in stationsAllResponse.stations) { if (stations.GetById(station.Value.station) != null) { // Can not add station to list of station. Id is not unique. throw new InvalidResponseException( string.Format("Station id {0} is not unique.", station.Value.station), stationsAllResponse); } stations.Add(new Station.Station( station.Value.station, station.Value.GetGroup(), station.Value.GetPosition(), station.Value.description, new Data(station.Value.operator_data?.operator_name, station.Value.operator_data?.operator_phone, station.Value.operator_data?.operator_hours, station.Value.operator_data?.operator_email, !string.IsNullOrEmpty(station.Value.operator_data?.operator_color) ? Color.FromHex(station.Value.operator_data?.operator_color) : (Color?)null))); } return stations; } /// /// Gets general data from COPRI response. /// /// Response to get data from. /// General data object initialized form COPRI response. public static GeneralData GetGeneralData(this ResponseBase response) => new GeneralData( response.init_map.GetMapSpan(), response.merchant_message, response.TryGetCopriVersion(out Version copriVersion) ? new Version(0, 0) : copriVersion, new ResourceUrls(response.tariff_info_html, response.bike_info_html, response.agb_html, response.privacy_html, response.impress_html)); /// Gets account object from login response. /// Needed to extract cookie from autorization response. /// Response to get session cookie and debug level from. /// Mail address needed to construct a complete account object (is not part of response). /// Password needed to construct a complete account object (is not part of response). public static IAccount GetAccount( this AuthorizationResponse loginResponse, string merchantId, string mail, string password) { if (loginResponse == null) { throw new ArgumentNullException(nameof(loginResponse)); } return new Account( mail, password, loginResponse.GetIsAgbAcknowledged(), loginResponse.authcookie?.Replace(merchantId, ""), loginResponse.GetGroup(), loginResponse.debuglevel == 1 ? Permissions.All : (Permissions)loginResponse.debuglevel); } /// Load bike object from booking response. /// Bike object to load from response. /// Booking response. /// Mail address of user which books bike. /// Controls whether notify property changed events are fired or not. public static void Load( this IBikeInfoMutable bike, BikeInfoReservedOrBooked bikeInfo, string mailAddress, NotifyPropertyChangedLevel notifyLevel = NotifyPropertyChangedLevel.All) { if (bike is Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable btBikeInfo) { btBikeInfo.LockInfo.Load( bikeInfo.GetBluetoothLockId(), bikeInfo.GetBluetoothLockGuid(), bikeInfo.GetSeed(), bikeInfo.GetUserKey(), bikeInfo.GetAdminKey()); } var l_oState = bikeInfo.GetState(); switch (l_oState) { case InUseStateEnum.Disposable: bike.State.Load( InUseStateEnum.Disposable, notifyLevel: notifyLevel); break; case InUseStateEnum.Reserved: bike.State.Load( InUseStateEnum.Reserved, bikeInfo.GetFrom(), mailAddress, bikeInfo.timeCode, notifyLevel); break; case InUseStateEnum.Booked: bike.State.Load( InUseStateEnum.Booked, bikeInfo.GetFrom(), mailAddress, bikeInfo.timeCode, notifyLevel); break; default: throw new Exception(string.Format("Unexpected bike state detected. state is {0}.", l_oState)); } } } }