using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using API.DTOs.ReadingLists; using API.Entities; using API.Helpers; using API.Interfaces.Repositories; using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.EntityFrameworkCore; namespace API.Data.Repositories { public class ReadingListRepository : IReadingListRepository { private readonly DataContext _context; private readonly IMapper _mapper; public ReadingListRepository(DataContext context, IMapper mapper) { _context = context; _mapper = mapper; } public void Update(ReadingList list) { _context.Entry(list).State = EntityState.Modified; } public void Remove(ReadingListItem item) { _context.ReadingListItem.Remove(item); } public void BulkRemove(IEnumerable items) { _context.ReadingListItem.RemoveRange(items); } public async Task> GetReadingListDtosForUserAsync(int userId, bool includePromoted, UserParams userParams) { var query = _context.ReadingList .Where(l => l.AppUserId == userId || (includePromoted && l.Promoted )) .OrderBy(l => l.LastModified) .ProjectTo(_mapper.ConfigurationProvider) .AsNoTracking(); return await PagedList.CreateAsync(query, userParams.PageNumber, userParams.PageSize); } public async Task GetReadingListByIdAsync(int readingListId) { return await _context.ReadingList .Where(r => r.Id == readingListId) .Include(r => r.Items.OrderBy(item => item.Order)) .SingleOrDefaultAsync(); } public async Task> GetReadingListItemDtosByIdAsync(int readingListId, int userId) { var userLibraries = _context.Library .Include(l => l.AppUsers) .Where(library => library.AppUsers.Any(user => user.Id == userId)) .AsNoTracking() .Select(library => library.Id) .ToList(); var items = await _context.ReadingListItem .Where(s => s.ReadingListId == readingListId) .Join(_context.Chapter, s => s.ChapterId, chapter => chapter.Id, (data, chapter) => new { TotalPages = chapter.Pages, ChapterNumber = chapter.Range, readingListItem = data }) .Join(_context.Volume, s => s.readingListItem.VolumeId, volume => volume.Id, (data, volume) => new { data.readingListItem, data.TotalPages, data.ChapterNumber, VolumeId = volume.Id, VolumeNumber = volume.Name, }) .Join(_context.Series, s => s.readingListItem.SeriesId, series => series.Id, (data, s) => new { SeriesName = s.Name, SeriesFormat = s.Format, s.LibraryId, data.readingListItem, data.TotalPages, data.ChapterNumber, data.VolumeNumber, data.VolumeId }) .Select(data => new ReadingListItemDto() { Id = data.readingListItem.Id, ChapterId = data.readingListItem.ChapterId, Order = data.readingListItem.Order, SeriesId = data.readingListItem.SeriesId, SeriesName = data.SeriesName, SeriesFormat = data.SeriesFormat, PagesTotal = data.TotalPages, ChapterNumber = data.ChapterNumber, VolumeNumber = data.VolumeNumber, LibraryId = data.LibraryId, VolumeId = data.VolumeId, ReadingListId = data.readingListItem.ReadingListId }) .Where(o => userLibraries.Contains(o.LibraryId)) .OrderBy(rli => rli.Order) .AsNoTracking() .ToListAsync(); // Attach progress information var fetchedChapterIds = items.Select(i => i.ChapterId); var progresses = await _context.AppUserProgresses .Where(p => fetchedChapterIds.Contains(p.ChapterId)) .AsNoTracking() .ToListAsync(); foreach (var progress in progresses) { var progressItem = items.SingleOrDefault(i => i.ChapterId == progress.ChapterId && i.ReadingListId == readingListId); if (progressItem == null) continue; progressItem.PagesRead = progress.PagesRead; } return items; } public async Task GetReadingListDtoByIdAsync(int readingListId, int userId) { return await _context.ReadingList .Where(r => r.Id == readingListId && (r.AppUserId == userId || r.Promoted)) .ProjectTo(_mapper.ConfigurationProvider) .SingleOrDefaultAsync(); } public async Task> AddReadingProgressModifiers(int userId, IList items) { var chapterIds = items.Select(i => i.ChapterId).Distinct().ToList(); var userProgress = await _context.AppUserProgresses .Where(p => p.AppUserId == userId && chapterIds.Contains(p.ChapterId)) .AsNoTracking() .ToListAsync(); foreach (var item in items) { var progress = userProgress.Where(p => p.ChapterId == item.ChapterId); item.PagesRead = progress.Sum(p => p.PagesRead); } return items; } public async Task GetReadingListDtoByTitleAsync(string title) { return await _context.ReadingList .Where(r => r.Title.Equals(title)) .ProjectTo(_mapper.ConfigurationProvider) .SingleOrDefaultAsync(); } public async Task> GetReadingListItemsByIdAsync(int readingListId) { return await _context.ReadingListItem .Where(r => r.ReadingListId == readingListId) .OrderBy(r => r.Order) .ToListAsync(); } } }