using Elternbeirat.Contracts;
namespace Elternbeirat.Web.Features.Posts;
///
/// The posts next to a given post in time: the one published before it and the
/// one published after it.
///
///
/// The older post, or if the post is the oldest.
///
///
/// The newer post, or if the post is the newest.
///
///
/// "Previous" and "next" follow time, as a reader moving through the news would:
/// "Vorheriger Beitrag" is the older one, "Nächster Beitrag" the newer one. The
/// list order of the posts page (newest first) is the other way round, which is
/// why the direction is pinned down here instead of being left to the markup.
///
///
public sealed record PostNeighbors(Post? Previous, Post? Next)
{
///
/// Finds the neighbours of the post with the given slug.
///
///
/// All public posts, newest first, as PocketBaseClient.GetPostsAsync
/// returns them.
///
/// The slug of the post being shown.
///
/// The older and the newer post. Both are if the slug is
/// not in the list, or if it is the only post.
///
///
/// The slug is compared case-insensitively, like the route lookup in
/// , so a page reached as /posts/New-Board still
/// gets its neighbours.
///
///
///
/// // posts = [March, February, January] (newest first)
/// var neighbors = PostNeighbors.Of(posts, "february");
/// // neighbors.Previous is January, neighbors.Next is March
///
///
public static PostNeighbors Of(IReadOnlyList posts, string slug) =>
IndexOf(posts, slug) is var index and >= 0
? new PostNeighbors(
Previous: index + 1 < posts.Count ? posts[index + 1] : null,
Next: index > 0 ? posts[index - 1] : null)
: new PostNeighbors(null, null);
///
/// The position of the post with , or -1.
///
private static int IndexOf(IReadOnlyList posts, string slug) =>
posts
.Select((post, index) => (post, index))
.FirstOrDefault(
entry => string.Equals(entry.post.Slug, slug, StringComparison.OrdinalIgnoreCase),
(null!, -1))
.index;
}