using System; using System.Collections.Generic; using System.Threading.Tasks; using Serilog; using TINK.Model.Bikes; using TINK.Model.Connector.Updater; using TINK.Model.Services.CopriApi; using TINK.Repository; using TINK.Services.CopriApi; using BikeInfo = TINK.Model.Bikes.BikeInfoNS.BC.BikeInfo; namespace TINK.Model.Connector { /// Provides query functionality for use without log in. public class CachedQuery : Base, IQuery { /// Cached copri server (connection to copri backed up by cache). private readonly ICachedCopriServer server; /// Constructs a copri query object. /// Server which implements communication. public CachedQuery( ICopriServerBase copriServer) : base(copriServer) { server = copriServer as ICachedCopriServer; if (server == null) { throw new ArgumentException($"Copri server is not of expected type. Type detected is {copriServer.GetType()}."); } } /// Gets all stations including positions and bikes. public async Task> GetBikesAndStationsAsync() { var resultStations = await server.GetStations(); if (resultStations.Source == typeof(CopriCallsMonkeyStore)) { // Communication with copri in order to get stations failed. return new Result( resultStations.Source, new StationsAndBikesContainer( resultStations.Response.GetStationsAllMutable(), new BikeCollection() /* There are no bikes occupied because user is not logged in. */), resultStations.GeneralData, resultStations.Exception); } // Communication with copri succeeded. server.AddToCache(resultStations); return new Result( resultStations.Source, new StationsAndBikesContainer( resultStations.Response.GetStationsAllMutable(), new BikeCollection()), resultStations.GeneralData); } /// Gets bikes occupied. /// Collection of bikes. public async Task> GetBikesOccupiedAsync() { Log.ForContext().Error("Unexpected call to get be bikes occupied detected. No user is logged in."); return new Result( typeof(CopriCallsMonkeyStore), await Task.FromResult(new BikeCollection(new Dictionary())), new GeneralData(), new Exception("Abfrage der reservierten/ gebuchten Räder nicht möglich. Kein Benutzer angemeldet.")); } /// Gets bikes available. /// Uri of the operator host to get bikes from or null if bikes have to be gotten form primary host. /// Id of station which is used for filtering bikes. Null if no filtering should be applied. /// Id of bike which is used for filtering bikes. Null if no filtering should be applied. /// Collection of bikes. public async Task> GetBikesAsync(Uri operatorUri = null, string stationId = null, string bikeId = null) { var result = await server.GetBikesAvailable(operatorUri: operatorUri, stationId: stationId, bikeId: bikeId); if (result.Source != typeof(CopriCallsMonkeyStore)) { server.AddToCache(result, operatorUri, stationId, bikeId); } return new Result( result.Source, result.Response.GetBikesAvailable(result.Source == typeof(CopriCallsMonkeyStore) ? Bikes.BikeInfoNS.BC.DataSource.Cache : Bikes.BikeInfoNS.BC.DataSource.Copri), result.GeneralData, result.Exception); } } }