using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace InABox.Core
{
    
    public interface IAutoEntityUnionGenerator : IAutoEntityGenerator
    {
        IAutoEntityUnionTable[] Tables { get; }
    }

    public interface IAutoEntityUnionConstant
    {
        object Value { get; }
        IColumn Mapping { get; }
    }

    public class AutoEntityUnionConstant : IAutoEntityUnionConstant
    {
        public object Value { get; private set; }
        public IColumn Mapping { get; private set; }

        public AutoEntityUnionConstant(object value, IColumn mapping)
        {
            Value = value;
            Mapping = mapping;
        }
    }
    
    public interface IAutoEntityUnionTable
    {
        Type Entity { get; }
        IFilter? Filter { get; }
        AutoEntityUnionConstant[] Constants { get; }
    }
    
    public class AutoEntityUnionTable<TInterface,TEntity> : IAutoEntityUnionTable
    {
        public Type Entity => typeof(TEntity);
        public IFilter? Filter { get; }
        
        
        private List<AutoEntityUnionConstant> _constants = new List<AutoEntityUnionConstant>();
        public AutoEntityUnionConstant[] Constants => _constants.ToArray();

        public AutoEntityUnionTable(Filter<TEntity>? filter)
        {
            Filter = filter;
        }
        
        public AutoEntityUnionTable<TInterface, TEntity> AddConstant<TType>(TType constant, Expression<Func<TInterface, object?>> mapping)
        {
            _constants.Add(new AutoEntityUnionConstant(constant, new Column<TInterface>(mapping)));
            return this;
        }
        
    }
    
    public abstract class AutoEntityUnionGenerator<TInterface> : IAutoEntityUnionGenerator
    {
        public AutoEntityUnionGenerator()
        {
            Configure();
        }

        private List<IAutoEntityUnionTable> _tables = new List<IAutoEntityUnionTable>();
                
        public IAutoEntityUnionTable[] Tables => _tables.ToArray();
        
        public AutoEntityUnionTable<TInterface, TType> AddTable<TType>(Filter<TType>? filter = null)
        {
            var table = new AutoEntityUnionTable<TInterface, TType>(filter);
            _tables.Add(table);
            return table;
        }
        
        protected abstract void Configure(); 
        
        public Type Definition => typeof(TInterface);
        
        public abstract bool Distinct { get; }

        public abstract Column<TInterface>[] IDColumns { get; }

        IColumn[] IAutoEntityGenerator.IDColumns => IDColumns;
    }
}