private async Task <PostViewModel[]> BrowseInternalAsync(int page, int pageSize, PostSortBy sortBy, PostSortDirection sortDirection, PostedSince postedSince, string[] tags, string author, string text)
        {
            var posts = await _postsRepository.BrowsePostsAsync(
                sortBy,
                sortDirection,
                postedSince,
                page,
                pageSize,
                tags,
                author,
                text,
                DateTimeOffset.UtcNow
                );

            return(posts.Select(post => PrepareForDisplay(post, true)).ToArray());
        }
        public Task <Post[]> BrowsePostsAsync(PostSortBy sortBy, PostSortDirection sortDirection, PostedSince since, int page,
                                              int pageSize, string[] tags, string author, string text, DateTimeOffset now)
        {
            if (page < 0)
            {
                throw new ArgumentException("Page must be greater than or equal to 0");
            }
            if (pageSize < 1)
            {
                throw new ArgumentException("Page must be greater than or equal to 1");
            }

            var query = DbContext.Posts
                        .AsNoTracking()
                        .Include(p => p.Author)
                        .Where(p => p.Published);

            if (since != PostedSince.Forever)
            {
                var dateTimeOffset = now.AddDays(-(int)since);
                query = sortBy == PostSortBy.Updated
                                        ? query.Where(p => p.DatePublished >= dateTimeOffset)
                                        : query.Where(p => p.DateCreated >= dateTimeOffset);
            }

            if (!string.IsNullOrWhiteSpace(author))
            {
                query = query.Where(p => p.Author.Username == author);
            }

            if (!string.IsNullOrWhiteSpace(text))
            {
                //TODO: Replace with ts_vector full text search when available
                query = query.Where(p => p.Text.Contains(text) || p.Title.Contains(text));
            }

            if (tags != null && tags.Length > 0)
            {
                query = tags.Aggregate(query, (curentQuery, tag) => curentQuery.Where(p => p.Tags.Any(pt => pt.Tag.Name == tag)));
            }

            switch (sortBy)
            {
            case PostSortBy.Votes:
                query = sortDirection == PostSortDirection.Down
                                                ? query.OrderByDescending(p => p.Votes).ThenByDescending(p => p.DateCreated)
                                                : query.OrderBy(p => p.Votes).ThenBy(p => p.DateCreated);
                break;

            case PostSortBy.Created:
                query = sortDirection == PostSortDirection.Down
                                                ? query.OrderByDescending(p => p.DateCreated)
                                                : query.OrderBy(p => p.DateCreated);
                break;

            case PostSortBy.Updated:
                query = sortDirection == PostSortDirection.Down
                                                ? query.OrderByDescending(p => p.DatePublished)
                                                : query.OrderBy(p => p.DatePublished);
                break;

            default:
                throw new ArgumentException($"Unknown sort by: {sortBy}", nameof(sortBy));
            }

            query = query
                    .Select(p => new Post
            {
                Id            = p.Id,
                Title         = p.Title,
                Author        = p.Author,
                Published     = p.Published,
                DateCreated   = p.DateCreated,
                DatePublished = p.DatePublished,
                ThumbnailUrn  = p.ThumbnailUrn,
                Tags          = p.Tags.Select(t => new PostTag {
                    Tag = t.Tag
                }).ToHashSet(),
                Votes = p.Votes
            })
                    .Skip(page * pageSize)
                    .Take(pageSize)
                    .Include(p => p.Tags)
                    .ThenInclude(p => p.Tag);

            return(query.ToArrayAsync());
        }