using System;
using System.Threading;
using System.Threading.Tasks;

namespace Dacryptero.Search.AST
{
    public abstract class AstBase
    {
        public virtual AstBase? Transform(Func<AstBase, AstBase?> transformer)
        {
            return transformer(this);
        }

        public virtual Sorting.SortConfig GetSortConfig()
        {
            return new Sorting.SortConfig(); 
        }

        public abstract Task<SearchIndex> GetSearchIndexAsync(DB.DBSingleController db,
            Data.IndexSource source, CancellationToken cancellationToken
        );

        public override string ToString()
        {
            return GetType().Name;
        }

        public abstract AstBase Clone();

        public abstract SearchProgress Check(SearchContext context);

#if DEBUG
        public static void Log(int level, Search.AST.AstBase entry)
        {
            var padding = new string(' ', level * 4);
            if (entry is Search.AST.Word word)
                Serilog.Log.Verbose("{padding}Word ({text})", padding, word.Text);
            else Serilog.Log.Verbose("{padding}{type}", padding, entry.GetType().Name);
            if (entry is Search.AST.Group group)
            {
                foreach (var opt in group.Options)
                    Serilog.Log.Verbose("{padding}  {option}", padding, opt);
            }
            if (entry is Search.AST.AstCollectionBase col)
            {
                foreach (var item in col.Items)
                    Log(level + 1, item);
            }
            if (entry is Search.AST.Negation negation)
            {
                Log(level + 1, negation.Item);
            }
        }
#endif
    }
}