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.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 interface IRepository : IDisposable, IAsyncDisposable where T : IRessource { 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); } 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); } public interface IEpisodeRepository : IRepository { Task Get(string showSlug, int seasonNumber, int episodeNumber); 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 Get(int episodeID, string languageTag, bool isForced); } public interface ILibraryRepository : IRepository {} public interface ICollectionRepository : IRepository {} public interface IGenreRepository : IRepository {} public interface IStudioRepository : IRepository {} 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); } public interface IProviderRepository : IRepository {} }