using System;
using System.Threading;
using System.Threading.Tasks;
using Dacryptero.DB;
using Dacryptero.Search.Sorting;

namespace Dacryptero.Search.AST
{
    public class Negation : AstBase
    {
        public AstBase Item { get; private set; }

        public Negation(AstBase item)
        {
            Item = item;
        }

        public override AstBase? Transform(Func<AstBase, AstBase?> transformer)
        {
            bool changed = false;
            var @new = Item.Transform(transformer);
            if (@new is not null)
            {
                Item = @new;
                changed = true;
            }
            @new = base.Transform(transformer);
            if (@new is not null)
                changed = true;
            return changed ? (@new ?? this) : null;
        }

        public override AstBase Clone()
        {
            return new Negation(Item.Clone());
        }

        public override SearchProgress Check(SearchContext context)
        {
            var client = Item.Check(context);
            return new SearchProgress(
                client.IsSuccess ? 0 : 1,
                new Collections.TreeCollection<ResultFound>()
            );
        }

        public override async Task<SearchIndex> GetSearchIndexAsync(DBSingleController db,
            Data.IndexSource source, CancellationToken cancellationToken
        )
        {
            var index = await Item.GetSearchIndexAsync(db, source, cancellationToken).ConfigureAwait(false);
            index.Negate();
            return index;
        }

        public override SortConfig GetSortConfig()
        {
            return Item.GetSortConfig().Negate();
        }
    }
}