using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dacryptero.Search.Sorting;

namespace Dacryptero.Search.AST
{
    public abstract class AstCollectionBase : AstBase, IEnumerable<AstBase>
    {
        public override AstBase? Transform(Func<AstBase, AstBase?> transformer)
        {
            var changed = false;
            AstBase? @new;
            for (int i = 0; i < Items.Count; ++i)
            {
                @new = Items[i].Transform(transformer);
                if (@new is not null)
                {
                    Items[i] = @new;
                    changed = true;
                }
            }

            @new = base.Transform(transformer);
            if (@new is not null)
                changed = true;
            return changed ? (@new ?? this) : null;
        }

        public List<AstBase> Items { get; set; } = new List<AstBase>();

        public IEnumerator<AstBase> GetEnumerator()
        {
            return ((IEnumerable<AstBase>)Items).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)Items).GetEnumerator();
        }
    
        public override AstBase Clone()
        {
            var @new = CloneCollection();
            @new.Items.Capacity = Items.Count;
            @new.Items.AddRange(Items.Select(x => x.Clone()));
            return @new;
        }

        protected abstract AstCollectionBase CloneCollection();

        public override SortConfig GetSortConfig()
        {
            var config = base.GetSortConfig();
            foreach (var item in Items)
            {
                config.Options.AddRange(item.GetSortConfig().Options);
            }
            return config;
        }
    }
}