using System;
using InABox.Core;

namespace InABox.Clients
{

    public class QueryDef : IQueryDef
    {
        public QueryDef(Type type)
        {
            Type = type;
        }

        public QueryDef(Type type, IFilter? filter = null, IColumns? columns = null, ISortOrder? sort = null, CoreRange? range = null)
        {
            Type = type;
            Filter = filter;
            Columns = columns;
            SortOrder = sort;
            Range = range;
        }

        public Type Type { get; private set; }
        public IFilter? Filter { get; set; }
        public IColumns? Columns { get; set; }
        public ISortOrder? SortOrder { get; set; }
        
        public CoreRange? Range { get; set; }
    }
    
    public class QueryDef<T> : IQueryDef where T : Entity, IRemotable, IPersistent, new()
    {
        public QueryDef(Filter<T>? filter = null, Columns<T>? columns = null, SortOrder<T>? sortorder = null, CoreRange? range = null)
        {
            Type = typeof(T);
            Filter = filter;
            Columns = columns;
            SortOrder = sortorder;
            Range = range;
        }

        public Type Type { get; }

        public IFilter? Filter { get; }

        public IColumns? Columns { get; }

        public ISortOrder? SortOrder { get; }
        
        public CoreRange? Range { get; set; }
        
    }

    public class KeyedQueryDef : QueryDef, IKeyedQueryDef
    {
        public string Key { get; }

        public KeyedQueryDef(string key, Type type, IFilter? filter = null, IColumns? columns = null, ISortOrder? sortOrder = null, CoreRange? range = null) : base(type)
        {
            Key = key;
            Filter = filter;
            Columns = columns;
            SortOrder = sortOrder;
            Range = range;
        }
    }

    public class KeyedQueryDef<T> : QueryDef<T>, IKeyedQueryDef where T : Entity, IRemotable, IPersistent, new()
    {
        public string Key { get; }

        public KeyedQueryDef(
            string key, 
            Filter<T>? filter = null,
            Columns<T>? columns = null,
            SortOrder<T>? sortorder = null,
            CoreRange? range = null)
                : base(filter, columns, sortorder, range)
        {
            Key = key;
        }
        public KeyedQueryDef(
            Filter<T>? filter = null,
            Columns<T>? columns = null,
            SortOrder<T>? sortorder = null,
            CoreRange? range = null): base(filter, columns, sortorder, range)
        {
            Key = typeof(T).Name;
        }
    }

    /*public class HeadQueryDef<T> : IQueryDef where T : Entity, new()
    {
        public HeadQueryDef(Filter<T> filter, Columns<T> columns, SortOrder<T> sortorder)
        {
            Type = typeof(T);
            Filter = filter;
            Columns = columns;
            SortOrder = sortorder;
        }

        public Type Type { get; set; }

        public object Filter { get; set; }

        public object Columns { get; set; }

        public object SortOrder { get; set; }
    }

    public interface IChildQueryDef : IQueryDef { }

    public class ChildQueryDef<T> : IChildQueryDef where T : Entity, new()
    {
        public ChildQueryDef(Filter<T> filter, Columns<T> columns, SortOrder<T> sortorder)
        {
            Type = typeof(T);
            Filter = filter;
            Columns = columns;
            SortOrder = sortorder;
        }

        public Type Type { get; set; }

        public object Filter { get; set; }

        public object Columns { get; set; }

        public object SortOrder { get; set; }
    }*/
}