using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TINK.Model.Bike; using TINK.Model.Connector.Filter; using TINK.Model.Services.CopriApi; using TINK.Model.Station; using BikeInfo = TINK.Model.Bike.BC.BikeInfo; namespace TINK.Model.Connector { /// Filters connector respones. /// Former name: Filter public class FilteredConnector : IFilteredConnector { /// Constructs a filter object. /// Filter group. /// Connector object. public FilteredConnector( IEnumerable group, IConnector connector) { Connector = connector; if (Connector == null) { throw new ArgumentException("Can not construct filter object. Connector- and command objects must not be null."); } Query = new QueryProvider(Connector.Query, GroupFilterFactory.Create(group)); } /// Inner connector object. public IConnector Connector { get; } /// Command object. public ICommand Command => Connector.Command; /// Object to query information. public IQuery Query { get; } /// True if connector has access to copri server, false if cached values are used. public bool IsConnected => Connector.IsConnected; /// Object to perform filtered queries. private class QueryProvider : IQuery { /// Holds the filter. private IGroupFilter Filter { get; } /// Holds the reference to object which performs copry queries. private IQuery m_oInnerQuery; /// Constructs a query object. /// /// public QueryProvider(IQuery innerQuerry, IGroupFilter filter) { m_oInnerQuery = innerQuerry; Filter = filter; } /// Gets bikes either bikes available if no user is logged in or bikes available and bikes occupied if a user is logged in. public async Task> GetBikesAsync() { var result = await m_oInnerQuery.GetBikesAsync(); return new Result( result.Source, new BikeCollection(DoFilter(result.Response, Filter)), result.GeneralData, result.Exception); } /// Gets bikes occupied if a user is logged in. public async Task> GetBikesOccupiedAsync() { var result = await m_oInnerQuery.GetBikesOccupiedAsync(); return new Result( result.Source, new BikeCollection(result.Response.ToDictionary(x => x.Id)), result.GeneralData, result.Exception); } /// Gets all station applying filter rules. /// public async Task> GetBikesAndStationsAsync() { // Bikes and stations from COPRI or cache var providerBikesAndStations = await m_oInnerQuery.GetBikesAndStationsAsync(); // Do filtering. var filteredStationsDictionary = new StationDictionary(providerBikesAndStations.Response.StationsAll.CopriVersion, DoFilter(providerBikesAndStations.Response.StationsAll, Filter)); var filteredBikesDictionary = new BikeCollection(DoFilter(providerBikesAndStations.Response.Bikes, Filter)); var filteredBikesAndStations = new Result( providerBikesAndStations.Source, new StationsAndBikesContainer(filteredStationsDictionary, filteredBikesDictionary), providerBikesAndStations.GeneralData, providerBikesAndStations.Exception); return filteredBikesAndStations; } /// Filter bikes by group. /// Bikes to filter. /// Filtered bikes. private static Dictionary DoFilter(BikeCollection bikes, IGroupFilter filter) { return bikes.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id); } /// Filter stations by broup. /// private static Dictionary DoFilter(StationDictionary stations, IGroupFilter filter) { return stations.Where(x => filter.DoFilter(x.Group).Count() > 0).ToDictionary(x => x.Id); } } } }