using InABox.Core;

namespace InABox.Database
{
    public interface IStore
    {
        bool IsSubStore { get; set; }

        Guid UserGuid { get; set; }
        string UserID { get; set; }

        Platform Platform { get; set; }
        string Version { get; set; }

        IProvider Provider { get; set; }
        
        // Called once at Database Startup to initialise caches etc
        void Init();
        
        IEnumerable<object[]> List(Filter<Entity>? filter = null, Columns<Entity>? columns = null, SortOrder<Entity>? sort = null);

        CoreTable Query(Filter<Entity>? filter = null, Columns<Entity>? columns = null, SortOrder<Entity>? sort = null);
        Entity[] Load(Filter<Entity>? filter = null, SortOrder<Entity>? sort = null);
        void Save(Entity entity, string auditnote);
        void Save(IEnumerable<Entity> entities, string auditnote);
        void Delete(Entity entity, string auditnote);
        void Delete(IEnumerable<Entity> entities, string auditnote);

        void BulkUpdate(IEnumerable<Entity> entities);
        
    }

    public interface IStore<T> : IStore where T : Entity, new()
    {
        IEnumerable<object[]> List(Filter<T>? filter = null, Columns<T>? columns = null, SortOrder<T>? sort = null);

        CoreTable Query(Filter<T>? filter = null, Columns<T>? columns = null, SortOrder<T>? sort = null);

        T[] Load(Filter<T>? filter = null, SortOrder<T>? sort = null);

        void Save(T entity, string auditnote);
        void Save(IEnumerable<T> entities, string auditnote);

        void Delete(T entity, string auditnote);
        void Delete(IEnumerable<T> entities, string auditnote);

        void BulkUpdate(IEnumerable<T> entities);


        //void ResetAggregate<TSource>(T entity, Expression<Func<TSource, object>> link, params IAggregate<TSource, T>[] aggregates) where TSource : Entity, new();
        //DoubleAggregate<T, TTarget> Sum<TTarget>(Expression<Func<T, double>> source, Expression<Func<TTarget, double>> target) where TTarget : Entity, new();
        //TimeSpanAggregate<T, TTarget> Sum<TTarget>(Expression<Func<T, TimeSpan>> source, Expression<Func<TTarget, TimeSpan>> target) where TTarget : Entity, new();
        //IntegerAggregate<T, TTarget> Sum<TTarget>(Expression<Func<T, int>> source, Expression<Func<TTarget, int>> target) where TTarget : Entity, new();
        //DoubleAggregate<T, TTarget> Count<TTarget>(Expression<Func<TTarget, double>> target) where TTarget : Entity, new();
        //TimeSpanAggregate<T, TTarget> Count<TTarget>(Expression<Func<TTarget, TimeSpan>> target) where TTarget : Entity, new();
        //IntegerAggregate<T, TTarget> Count<TTarget>(Expression<Func<TTarget, int>> target) where TTarget : Entity, new();
    }
}