using Serilog; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using TINK.Model.Station; using BikeInfo = TINK.Model.Bike.BC.BikeInfo; using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable; namespace TINK.Model.Bike { /// Holds entity of bikes. public class BikeCollectionMutable : ObservableCollection, IBikeDictionaryMutable { /// Constructs a mutable bike collection object. public BikeCollectionMutable() { SelectedBike = null; } /// /// Updates bikes dictionary from bikes response, i.e. /// - removes bikes which are no more contained in bikes response /// - updates state of all bikes from state contained in bikes response /// /// Object holding bikes info from copri to update from. Holds station id but not station name. /// All stations to get station names from. /// Provices date time information. public void Update(IEnumerable bikesAll, IEnumerable stations) { // Get list of current bikes by state(s) to update. // Needed to remove bikes which switched state and have to be removed from collection. var bikesToBeRemoved = this.Select(x => x.Id).ToList(); foreach (var bikeInfo in bikesAll ?? new List()) { // Get name of station form station id. var stationName = stations?.FirstOrDefault(x => x.Id == bikeInfo.StationId)?.StationName ?? string.Empty; if (string.IsNullOrEmpty(stationName)) Log.ForContext().Debug($"No name for station with id {bikeInfo.StationId} found."); // Check if bike has to be added to list of existing station. if (ContainsKey(bikeInfo.Id) == false) { // Bike does not yet exist in list of bikes. Add(BikeInfoMutableFactory.Create(bikeInfo, stationName)); continue; } // Update bike. GetById(bikeInfo.Id).State.Load(bikeInfo.State); if (bikesToBeRemoved.Contains(bikeInfo.Id)) { // Remove list from obsolete list. bikesToBeRemoved.Remove(bikeInfo.Id); } } // Remove obsolete bikes. foreach (var stationId in bikesToBeRemoved) { RemoveById(stationId); } } /// /// Adds a new bike to collecion of bike. /// /// New bike to add. /// Thrown if bike is not unique. public new void Add(BikeInfoMutable newBike) { // Ensure that bike id of new bike is is unique foreach (BikeInfoMutable bike in Items) { if (bike.Id == newBike.Id) { throw new Exception(string.Format("Can not add bike with {0} to collection ob bike. Id is not unnique.", newBike)); } } base.Add(newBike); } /// /// Bike selected by user for regerving or cancel reservation. /// public BikeInfoMutable SelectedBike { get; private set; } public void SetSelectedBike(string id) { SelectedBike = GetById(id); } /// /// Gets a bike by its id. /// /// /// public BikeInfoMutable GetById(string id) { { return this.FirstOrDefault(bike => bike.Id == id); } } /// /// Deteermines whether a bike by given key exists. /// /// Key to check. /// True if bike exists. public bool ContainsKey(string id) { return GetById(id) != null; } /// /// Removes a bike by its id. /// /// Id of bike to be removed. public void RemoveById(string id) { var l_oBike = GetById(id); if (l_oBike == null) { // Nothing to do if bike does not exists. return; } Remove(l_oBike); } /// /// Create mutable objects from immutable objects. /// private static class BikeInfoMutableFactory { public static BikeInfoMutable Create(BikeInfo bikeInfo, string stationName) { return (bikeInfo is BluetoothLock.BikeInfo bluetoothLockBikeInfo) ? new BluetoothLock.BikeInfoMutable(bluetoothLockBikeInfo, stationName) : new BikeInfoMutable(bikeInfo, stationName); } } } }