package net.minecraft.client.searchtree;

import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import net.minecraft.resources.ResourceLocation;
import java.util.stream.Stream;
import java.util.function.Function;

public class ReloadableSearchTree<T> extends ReloadableIdSearchTree<T> {
    protected SuffixArray<T> tree;
    private final Function<T, Stream<String>> filler;
    
    public ReloadableSearchTree(final Function<T, Stream<String>> function1, final Function<T, Stream<ResourceLocation>> function2) {
        super(function2);
        this.tree = new SuffixArray<T>();
        this.filler = function1;
    }
    
    @Override
    public void refresh() {
        this.tree = new SuffixArray<T>();
        super.refresh();
        this.tree.generate();
    }
    
    @Override
    protected void index(final T object) {
        super.index(object);
        this.filler.apply(object).forEach(string -> this.tree.add(object, string.toLowerCase(Locale.ROOT)));
    }
    
    @Override
    public List<T> search(final String string) {
        final int integer3 = string.indexOf(58);
        if (integer3 < 0) {
            return this.tree.search(string);
        }
        final List<T> list4 = this.namespaceTree.search(string.substring(0, integer3).trim());
        final String string2 = string.substring(integer3 + 1).trim();
        final List<T> list5 = this.pathTree.search(string2);
        final List<T> list6 = this.tree.search(string2);
        return Lists.newArrayList(new IntersectionIterator<>(list4.iterator(), new MergingUniqueIterator<>(list5.iterator(), list6.iterator(), this::comparePosition), this::comparePosition));
    }
    
    static class MergingUniqueIterator<T> extends AbstractIterator<T> {
        private final PeekingIterator<T> firstIterator;
        private final PeekingIterator<T> secondIterator;
        private final Comparator<T> orderT;
        
        public MergingUniqueIterator(final Iterator<T> iterator1, final Iterator<T> iterator2, final Comparator<T> comparator) {
            this.firstIterator = Iterators.<T>peekingIterator(iterator1);
            this.secondIterator = Iterators.<T>peekingIterator(iterator2);
            this.orderT = comparator;
        }
        
        @Override
        protected T computeNext() {
            final boolean boolean2 = !this.firstIterator.hasNext();
            final boolean boolean3 = !this.secondIterator.hasNext();
            if (boolean2 && boolean3) {
                return this.endOfData();
            }
            if (boolean2) {
                return this.secondIterator.next();
            }
            if (boolean3) {
                return this.firstIterator.next();
            }
            final int integer4 = this.orderT.compare(this.firstIterator.peek(), this.secondIterator.peek());
            if (integer4 == 0) {
                this.secondIterator.next();
            }
            return (integer4 <= 0) ? this.firstIterator.next() : this.secondIterator.next();
        }
    }
}
