using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Runtime.InteropServices; using System.Threading.Tasks; using JetBrains.Annotations; using Kyoo.Models; namespace Kyoo.Controllers { public readonly struct Pagination { public int Count { get; } public int AfterID { get; } public Pagination(int count, int afterID = 0) { Count = count; AfterID = afterID; } public static implicit operator Pagination(int limit) => new Pagination(limit); } public struct Sort { public Expression> Key; public bool Descendant; public Sort(Expression> key, bool descendant = false) { Key = key; Descendant = descendant; if (Key == null || Key.Body is MemberExpression || Key.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)Key.Body).Operand is MemberExpression) return; throw new ArgumentException("The given sort key is not valid."); } public Sort(string sortBy) { if (string.IsNullOrEmpty(sortBy)) { Key = null; Descendant = false; return; } string key = sortBy.Contains(':') ? sortBy.Substring(0, sortBy.IndexOf(':')) : sortBy; string order = sortBy.Contains(':') ? sortBy.Substring(sortBy.IndexOf(':') + 1) : null; ParameterExpression param = Expression.Parameter(typeof(T), "x"); MemberExpression property = Expression.Property(param, key); Key = property.Type.IsValueType ? Expression.Lambda>(Expression.Convert(property, typeof(object)), param) : Expression.Lambda>(property, param); Descendant = order switch { "desc" => true, "asc" => false, null => false, _ => throw new ArgumentException($"The sort order, if set, should be :asc or :desc but it was :{order}.") }; } public Sort To() { return new Sort(Key.Convert>(), Descendant); } } public interface IRepository : IDisposable, IAsyncDisposable where T : IResource { Task Get(int id); Task Get(string slug); Task> Search(string query); Task> GetAll(Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetAll([Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetAll(where, new Sort(sort), limit); Task Create([NotNull] T obj); Task CreateIfNotExists([NotNull] T obj); Task Edit([NotNull] T edited, bool resetOld); Task Delete(int id); Task Delete(string slug); Task Delete([NotNull] T obj); Task DeleteRange(params T[] objs) => DeleteRange(objs.AsEnumerable()); Task DeleteRange(IEnumerable objs); Task DeleteRange(params int[] ids) => DeleteRange(ids.AsEnumerable()); Task DeleteRange(IEnumerable ids); Task DeleteRange(params string[] slugs) => DeleteRange(slugs.AsEnumerable()); Task DeleteRange(IEnumerable slugs); } public interface IShowRepository : IRepository { Task AddShowLink(int showID, int? libraryID, int? collectionID); Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromLibrary(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(id, where, new Sort(sort), limit); Task> GetFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromLibrary(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(slug, where, new Sort(sort), limit); Task> GetFromCollection(int id, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromCollection(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromCollection(id, where, new Sort(sort), limit); Task> GetFromCollection(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromCollection(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromCollection(slug, where, new Sort(sort), limit); Task GetFromSeason(int seasonID); Task GetFromEpisode(int episodeID); } public interface ISeasonRepository : IRepository { Task Get(int showID, int seasonNumber); Task Get(string showSlug, int seasonNumber); Task Delete(string showSlug, int seasonNumber); Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); Task GetFromEpisode(int episodeID); } public interface IEpisodeRepository : IRepository { Task Get(int showID, int seasonNumber, int episodeNumber); Task Get(string showSlug, int seasonNumber, int episodeNumber); Task Get(int seasonID, int episodeNumber); Task GetAbsolute(int showID, int absoluteNumber); Task GetAbsolute(string showSlug, int absoluteNumber); Task Delete(string showSlug, int seasonNumber, int episodeNumber); Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); Task> GetFromSeason(int seasonID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromSeason(int seasonID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromSeason(seasonID, where, new Sort(sort), limit); Task> GetFromSeason(int showID, int seasonNumber, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromSeason(int showID, int seasonNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromSeason(showID, seasonNumber, where, new Sort(sort), limit); Task> GetFromSeason(string showSlug, int seasonNumber, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromSeason(string showSlug, int seasonNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromSeason(showSlug, seasonNumber, where, new Sort(sort), limit); } public interface ITrackRepository : IRepository { Task> GetFromEpisode(int episodeID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromEpisode(int episodeID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromEpisode(episodeID, where, new Sort(sort), limit); Task> GetFromEpisode(int showID, int seasonNumber, int episodeNumber, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromEpisode(int showID, int seasonNumber, int episodeNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromEpisode(showID, seasonNumber, episodeNumber, where, new Sort(sort), limit); Task> GetFromEpisode(string showSlug, int seasonNumber, int episodeNumber, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromEpisode(string showSlug, int seasonNumber, int episodeNumber, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromEpisode(showSlug, seasonNumber, episodeNumber, where, new Sort(sort), limit); } public interface ILibraryRepository : IRepository { Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); Task> GetFromCollection(int id, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromCollection(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromCollection(id, where, new Sort(sort), limit); Task> GetFromCollection(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromCollection(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromCollection(slug, where, new Sort(sort), limit); } public interface ILibraryItemRepository : IRepository { public Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); public Task> GetFromLibrary(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(id, where, new Sort(sort), limit); public Task> GetFromLibrary(string librarySlug, Expression> where = null, Sort sort = default, Pagination limit = default); public Task> GetFromLibrary(string librarySlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(librarySlug, where, new Sort(sort), limit); } public interface ICollectionRepository : IRepository { Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); Task> GetFromLibrary(int id, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromLibrary(int id, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(id, where, new Sort(sort), limit); Task> GetFromLibrary(string slug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromLibrary(string slug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromLibrary(slug, where, new Sort(sort), limit); } public interface IGenreRepository : IRepository { Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); } public interface IStudioRepository : IRepository { Task GetFromShow(int showID); Task GetFromShow(string showSlug); } public interface IPeopleRepository : IRepository { Task> GetFromShow(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showID, where, new Sort(sort), limit); Task> GetFromShow(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromShow(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromShow(showSlug, where, new Sort(sort), limit); Task> GetFromPeople(int showID, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromPeople(int showID, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromPeople(showID, where, new Sort(sort), limit); Task> GetFromPeople(string showSlug, Expression> where = null, Sort sort = default, Pagination limit = default); Task> GetFromPeople(string showSlug, [Optional] Expression> where, Expression> sort, Pagination limit = default ) => GetFromPeople(showSlug, where, new Sort(sort), limit); } public interface IProviderRepository : IRepository {} }