using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sony.Filtr.Core.SpotifyCharts.Data; using Sony.Filtr.DistributedCaching; namespace Sony.Filtr.Core.SpotifyCharts { public class SpotifyChartsManager { private readonly SpotifyChartsFactory _chartsFactory; private readonly DistributedCacheHandler _cacheHandler; private const string _cacheKeyAvailableCharts = "SpotifyCharts_AvailableCharts"; private const string _cacheKeyAvailableChartsOverview = "SpotifyCharts_AvailableChartsOverview-1.0-"; private const string _cacheKeyChartTimeWindows = "SpotifyCharts_ChartTimeWindows"; private const string _cacheKeyChartDates = "SpotifyCharts_ChartDates_"; private const string _cacheKeyChart = "SpotifyCharts_Chart_"; private const string _cacheKeyTrackChart = "SpotifyCharts_TrackChart_"; public SpotifyChartsManager(SpotifyChartsFactory chartsFactory, DistributedCacheHandler cacheHandler) { _chartsFactory = chartsFactory; _cacheHandler = cacheHandler; } public async Task> GetProcessedChartsForMarketAsync(string market) { return await this._chartsFactory.GetProcessedChartsForMarketAsync(market); } public async Task> GetAvailableChartsOverviewAsync() { var cacheKey = _cacheKeyAvailableChartsOverview; var availableChartOverview = _cacheHandler.Get(cacheKey) as List; if (availableChartOverview == null) { availableChartOverview = await _chartsFactory.GetAvailableChartsOverviewAsync(); _cacheHandler.Put(cacheKey, availableChartOverview); } return availableChartOverview; } public async Task>> GetAvailableChartsAsync(string market = null, SpotifyChartsListType? listType = null, SpotifyChartsTimeWindow? timeWindow = null) { var cacheKey = GetAvailableChartsCacheKey(); var availableCharts = _cacheHandler.Get(cacheKey) as Dictionary>; if (availableCharts == null) { availableCharts = await _chartsFactory.GetAvailableChartsAsync(); _cacheHandler.Put(cacheKey, availableCharts); } if (!string.IsNullOrWhiteSpace(market)) { availableCharts = availableCharts.Where(c => c.Key.Equals(market, StringComparison.InvariantCultureIgnoreCase)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } if (listType != null) { availableCharts = availableCharts.ToDictionary(chart => chart.Key, chart => chart.Value.Where(p => p.ListType == listType.Value).ToList()); } if (timeWindow != null) { availableCharts = availableCharts.ToDictionary(chart => chart.Key, chart => chart.Value.Where(p => p.TimeWindow == timeWindow.Value).ToList()); } return availableCharts; } private string GetAvailableChartsCacheKey() { var cacheKey = _cacheKeyAvailableCharts; return cacheKey; } private string GetAvailableChartsOverviewCacheKey() { var cacheKey = _cacheKeyAvailableChartsOverview; return cacheKey; } public async Task> GetChartDatesAsync(string market, SpotifyChartsListType chartType, SpotifyChartsTimeWindow timeWindow) { var cacheKey = GetDateCacheKey(market, chartType, timeWindow); var chartDates = _cacheHandler.Get(cacheKey) as List; if (chartDates == null) { chartDates = await _chartsFactory.GetChartDatesAsync(market, chartType, timeWindow); _cacheHandler.Put(cacheKey, chartDates); } return chartDates; } public async Task GetChartAsync(string market, SpotifyChartsListType listType, SpotifyChartsTimeWindow timeWindow, DateTime date) { var cacheKey = GetChartCacheKey(market, listType, timeWindow, date); var chart = _cacheHandler.Get(cacheKey) as SpotifyChart; if (chart == null) { chart = await _chartsFactory.GetChartAsync(market, listType, timeWindow, date); _cacheHandler.Put(cacheKey, chart); } return chart; } public async Task> GetTrackChartPositions(string isrc) { var cacheKey = _cacheKeyTrackChart + isrc; var trackCharts = _cacheHandler.Get(cacheKey) as List; if (trackCharts == null) { trackCharts = await _chartsFactory.GetAllTrackPositionsAsync(isrc); _cacheHandler.Put(cacheKey, trackCharts, DateTime.Now.AddDays(1)); } return trackCharts; } public async Task>> GetChartSummaryForTrackAsync(string isrc) { // Use available charts to be able to set null values for charts where track has never had a position //var availableCharts = await GetAvailableChartsOverviewAsync(); //var allCurrentAndPreviosPositions = await _chartsFactory.GetCurrentAndPreviousPositionAsync(isrc); //var allEntryAndLatestPositions = await _chartsFactory.GetEntryAndLatestPositionAsync(isrc); //var allPeakPositions = await _chartsFactory.GetPeakPositionsAsync(isrc); var availableChartsTask = GetAvailableChartsOverviewAsync(); var allCurrentAndPreviosPositionsTask = _chartsFactory.GetCurrentAndPreviousPositionAsync(isrc); var allEntryAndLatestPositionsTask = _chartsFactory.GetEntryAndLatestPositionAsync(isrc); var allPeakPositionsTask = _chartsFactory.GetPeakPositionsAsync(isrc); var availableCharts = await availableChartsTask; var allCurrentAndPreviosPositions = await allCurrentAndPreviosPositionsTask; var allEntryAndLatestPositions = await allEntryAndLatestPositionsTask; var allPeakPositions = await allPeakPositionsTask; var summariesPerMarket = new Dictionary>(); foreach (var marketGroup in availableCharts.GroupBy(c=> c.Market)) { var market = marketGroup.Key; summariesPerMarket.Add(market, new List()); var availableChartTypes = marketGroup.GroupBy(c => new { c.ListType, c.TimeWindow }); foreach (var chartsOfType in availableChartTypes) { var listType = chartsOfType.First().ListType; var timeWindow = chartsOfType.First().TimeWindow; try { var currentAndPreviousPositions = allCurrentAndPreviosPositions.SingleOrDefault(p => p.Market == market && p.ListType == listType && p.TimeWindow == timeWindow); var entryAndLatestPositions = allEntryAndLatestPositions.SingleOrDefault(p => p.Market == market && p.ListType == listType && p.TimeWindow == timeWindow); var peakPositions = allPeakPositions.SingleOrDefault(p => p.Market == market && p.ListType == listType && p.TimeWindow == timeWindow); summariesPerMarket[market].Add(new TrackChartSummary() { ListType = listType, TimeWindow = timeWindow, EntryDate = entryAndLatestPositions?.EarliestDate, EntryPosition = entryAndLatestPositions?.EarliestPosition, PeakDate = peakPositions?.EarliestPeakDate, PeakPosition = peakPositions?.PeakPosition, PeakLatestDate = peakPositions?.LatestPeakDate, LatestDate = entryAndLatestPositions?.LatestDate, LatestPosition = entryAndLatestPositions?.LatestPosition, CurrentPosition = currentAndPreviousPositions?.CurrentPosition, PreviousPosition = currentAndPreviousPositions?.PreviousPosition, LatestUpdateDate = chartsOfType.First().LatestDate, LatestUpdateTimestamp = chartsOfType.First().LatestTimestamp, }); } catch(Exception e) { Console.WriteLine(e); } } } return summariesPerMarket; } public async Task SetAvailableChartAsync(string market, DateTime date, SpotifyChartsListType listType, SpotifyChartsTimeWindow timeWindow, int version) { await _chartsFactory.SetAvailableChartAsync(market, date, listType, timeWindow, version); _cacheHandler.Remove(GetAvailableChartsCacheKey()); _cacheHandler.Remove(GetAvailableChartsOverviewCacheKey()); _cacheHandler.Remove(GetChartTimeWindowCacheKey(market, listType)); _cacheHandler.Remove(GetDateCacheKey(market, listType, timeWindow)); _cacheHandler.Remove(GetChartCacheKey(market, listType, timeWindow, date)); } private string GetChartTimeWindowCacheKey(string market, SpotifyChartsListType listType) { return _cacheKeyChartTimeWindows + "_" + market + "_" + listType; } private string GetDateCacheKey(string market, SpotifyChartsListType chartType, SpotifyChartsTimeWindow timeWindow) { return _cacheKeyChartDates + market.ToLowerInvariant() + "_" + chartType + "_" + timeWindow; } private string GetChartCacheKey(string market, SpotifyChartsListType chartType, SpotifyChartsTimeWindow timeWindow, DateTime date) { return _cacheKeyChart + "_" + market.ToLowerInvariant() + "_" + chartType + "_" + timeWindow + "_" + date; } public async Task GetLatestTrackInfoAsync(string market, string isrc, SpotifyChartsListType listType, SpotifyChartsTimeWindow timeWindow) { var earliestPositionTask = _chartsFactory.GetEarliestTrackPositionAsync(market, isrc, listType, timeWindow); var latestPositionTask = _chartsFactory.GetLatestTrackPositionAsync(market, isrc, listType, timeWindow); var earliestPeakPositionTask = _chartsFactory.GetEarliestPeakPositionAsync(market, isrc, listType, timeWindow); var latestPeakPositionTask = _chartsFactory.GetLatestPeakPositionAsync(market, isrc, listType, timeWindow); var currentPositionTask = _chartsFactory.GetCurrentTrackPosition(market, isrc, listType, timeWindow); var positions = new SimpleTrackSummary() { EarliestPosition = await earliestPositionTask, LatestPosition = await latestPositionTask, EarliestPeakPosition = await earliestPeakPositionTask, LatestPeakPosition = await latestPeakPositionTask, CurrentPosition = await currentPositionTask }; return positions; } } }