using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using TINK.Model.Device; using TINK.Repository.Exception; namespace TINK.Repository.Request { /// Creates requests if a user is logged in. public class RequestBuilderLoggedIn : IRequestBuilder { /// Constructs a object for building requests. /// public RequestBuilderLoggedIn( string merchantId, string sessionCookie) { MerchantId = !string.IsNullOrEmpty(merchantId) ? merchantId : throw new ArgumentException("Merchant id must not be null.", nameof(merchantId)); SessionCookie = !string.IsNullOrEmpty(sessionCookie) ? sessionCookie : throw new ArgumentException("Session cookie must not be null.", nameof(sessionCookie)); } /// Holds the id denoting the merchant (TINK app). public string MerchantId { get; } /// Holds the session cookie if a user is logged in. public string SessionCookie { get; } /// Gets request to log user in. /// Mailaddress of user to log in. /// Password to log in. /// Id specifying user and hardware. /// Response which holds auth cookie public string DoAuthorization( string mailAddress, string password, string deviceId) { throw new CallNotRequiredException(); } /// Logs user out. public string DoAuthout() { return $"request=authout&authcookie={SessionCookie}{MerchantId}"; } /// Gets bikes available. /// Request to query list of bikes available. public string GetBikesAvailable() { return RequestBuilder.GetBikesAvailable(MerchantId, SessionCookie); } /// Gets a list of bikes reserved/ booked by acctive user from Copri. /// Request to query list of bikes occupied. public string GetBikesOccupied() { return !string.IsNullOrEmpty(SessionCookie) ? $"request=user_bikes_occupied&system=all&genkey=1&authcookie={SessionCookie}{MerchantId}" : "request=bikes_available"; } /// Get list of stations from file. /// Request to query list of station. public string GetStations() { return $"request=stations_available&authcookie={SessionCookie ?? string.Empty}{MerchantId}"; } /// Gets reservation request (synonym: reservation == request == reservieren). /// Operator specific call. /// Id of the bike to reserve. /// Requst to reserve bike. public string DoReserve(string bikeId) => $"request=booking_request&bike={bikeId}&authcookie={SessionCookie}{MerchantId}"; /// Gets request to cancel reservation. /// Operator specific call. /// Id of the bike to cancel reservation for. /// Requst on cancel booking request. public string DoCancelReservation(string p_iBikeId) => $"request=booking_cancel&bike={p_iBikeId}&authcookie={SessionCookie}{MerchantId}"; /// Request to get keys. /// Operator specific call. /// Id of the bike to get keys for. /// Request to get keys. public string CalculateAuthParameters(string bikeId) => $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&genkey=1"; /// Gets the request for notifying about start of returning sequence. /// Operator specific call. /// Id of the bike to return. /// Request to notify about start of returning sequence. public string StartReturningBike(string bikeId) => $"request=booking_update&bike={bikeId}&lock_state=locking&authcookie={SessionCookie}{MerchantId}"; /// Gets the request for updating lock state for a booked bike. /// Operator specific call. /// Id of the bike to update locking state for. /// New locking state. /// Request to update locking state. public string UpateLockingState( string bikeId, lock_state state, LocationDto geolocation, double batteryPercentage) => $"request=booking_update&bike={bikeId}{GetLocationParameters(geolocation)}&lock_state={state}{GetBatteryPercentageParameters(batteryPercentage)}&authcookie={SessionCookie}{MerchantId}"; /// Gets booking request request (synonym: booking == renting == mieten). /// Operator specific call. /// Id of the bike to book. /// Used to publish GUID from app to copri. Used for initial setup of bike in copri. /// Holds the filling level percentage of the battery. /// Request to booking bike. public string DoBook(string bikeId, Guid guid, double batteryPercentage) => $"request=booking_update&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&Ilockit_GUID={guid}&state=occupied&lock_state=unlocked{GetBatteryPercentageParameters(batteryPercentage)}"; /// Gets the request to book and start opening the bike (synonym: booking == renting == mieten). /// Id of the bike to book. /// Request to booking bike. public string BookAndStartOpening(string bikeId) => $"request=booking_request&bike={bikeId}&authcookie={SessionCookie}{MerchantId}&state=occupied&lock_state={lock_state.unlocking}"; /// Gets request for returning the bike. /// Operator specific call. /// Id of bike to return. /// Geolocation of lock when returning bike. /// Requst on returning request. public string DoReturn(string bikeId, LocationDto geolocation, ISmartDevice smartDevice) => $"request=booking_update" + $"&bike={bikeId}" + $"&authcookie={SessionCookie}{MerchantId}" + $"&state=available" + $"{GetLocationParameters(geolocation)}" + $"&lock_state=locked" + $"{GetSmartDeviceParameters(smartDevice)}"; /// Returns a bike and starts closing. /// Id of the bike to return. /// Provides info about hard and software. /// Response to send to corpi. public string ReturnAndStartClosing(string bikeId, ISmartDevice smartDevice) => $"request=booking_update" + $"&bike={bikeId}" + $"&authcookie={SessionCookie}{MerchantId}" + $"&state=available" + $"&lock_state={lock_state.locking}" + $"{GetSmartDeviceParameters(smartDevice)}"; /// Gets submit feedback request. /// Id of the bike to return. /// General purpose message or error description. /// True if bike is broken. /// Submit feedback request. public string DoSubmitFeedback( string bikeId, string message = null, bool isBikeBroken = false) { if (string.IsNullOrEmpty(message) && !isBikeBroken) { // User just acknoledged biked returned message. return $"request=user_feedback&bike={bikeId}&authcookie={SessionCookie}{MerchantId}"; } if (isBikeBroken == false) { // Bike is ok and user entered a feedback message. return $"request=user_feedback&bike={bikeId}&message={WebUtility.UrlEncode(message)}&authcookie={SessionCookie}{MerchantId}"; } if (string.IsNullOrEmpty(message)) { // User just marked bike as broken without comment. return $"request=user_feedback&bike={bikeId}&bike_broken=1&authcookie={SessionCookie}{MerchantId}"; } // Bike is marked as broken and user added a comment. return $"request=user_feedback&bike={bikeId}&bike_broken=1&message={WebUtility.UrlEncode(message)}&authcookie={SessionCookie}{MerchantId}"; } private string GetBatteryPercentageParameters(double batteryPercentage) => !double.IsNaN(batteryPercentage) ? $"&voltage={batteryPercentage.ToString(CultureInfo.InvariantCulture)}" : string.Empty; /// Gets the geolocation parameter. /// Geolocation or null. private string GetLocationParameters(LocationDto geolocation) { if (geolocation == null) return string.Empty; if (geolocation.Accuracy == null) return $"&gps={geolocation.Latitude.ToString(CultureInfo.InvariantCulture)},{ geolocation.Longitude.ToString(CultureInfo.InvariantCulture)}&gps_age={geolocation.Age.TotalSeconds}"; return $"&gps={geolocation.Latitude.ToString(CultureInfo.InvariantCulture)},{geolocation.Longitude.ToString(CultureInfo.InvariantCulture)}&gps_accuracy={geolocation.Accuracy.Value.ToString(CultureInfo.InvariantCulture)}&gps_age={geolocation.Age.TotalSeconds}"; } /// Gets the geolocation parameter. /// Geolocation or null. private string GetSmartDeviceParameters(ISmartDevice smartDevice) => smartDevice != null ? $"{(!string.IsNullOrEmpty(smartDevice.Manufacturer) ? $"&user_device_manufaturer={smartDevice.Manufacturer})" : string.Empty)}" + $"{(!string.IsNullOrEmpty(smartDevice.Model) ? $"&user_device_model={smartDevice.Model}" : string.Empty)}" + $"{(!string.IsNullOrEmpty(smartDevice.PlatformText) ? $"&user_device_platform={smartDevice.PlatformText}" : string.Empty)}" + $"{(!string.IsNullOrEmpty(smartDevice.VersionText) ? $"&user_device_version={smartDevice.VersionText}" : string.Empty)}" + $"{(!string.IsNullOrEmpty(smartDevice.Identifier) ? $"&user_device_id={smartDevice.Identifier}" : string.Empty)}" : string.Empty; /// /// Gets request for submiting mini survey to copri server. /// /// Collection of answers. public string DoSubmitMiniSurvey(IDictionary answers) { // Remove entires which invalid keys or values. var validAnsers = answers?.Where(x => !string.IsNullOrEmpty(x.Key?.Trim()) && !string.IsNullOrEmpty(x.Value?.Trim())); // Create quersy return validAnsers != null && validAnsers.Count() > 0 ? $"request=user_minianswer&{string.Join("&", validAnsers.Select(x => $"{x.Key}={WebUtility.UrlEncode(x.Value)}"))}&authcookie={SessionCookie}{MerchantId}" : $"request=user_minianswer&authcookie={SessionCookie}{MerchantId}"; } } }