package net.minecraft.server.packs.repository;

import javax.annotation.Nullable;
import java.util.Comparator;
import java.util.Iterator;
import com.google.common.base.Functions;
import java.util.function.Predicate;
import java.util.Objects;
import java.util.Collection;
import java.util.stream.Collector;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.LinkedHashSet;
import java.util.function.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class PackRepository<T extends UnopenedPack> implements AutoCloseable {
    private final Set<RepositorySource> sources;
    private final Map<String, T> available;
    private final List<T> selected;
    private final UnopenedPack.UnopenedPackConstructor<T> constructor;
    
    public PackRepository(final UnopenedPack.UnopenedPackConstructor<T> b) {
        this.sources = Sets.newHashSet();
        this.available = Maps.newLinkedHashMap();
        this.selected = Lists.newLinkedList();
        this.constructor = b;
    }
    
    public void reload() {
        this.close();
        final Set<String> set2 = this.selected.stream().map(UnopenedPack::getId).collect(Collectors.toCollection((Supplier<R>)LinkedHashSet::new));
        this.available.clear();
        this.selected.clear();
        for (final RepositorySource yr4 : this.sources) {
            yr4.<T>loadPacks(this.available, this.constructor);
        }
        this.sortAvailable();
        this.selected.addAll(set2.stream().map(this.available::get).filter(Objects::nonNull).collect(Collectors.toCollection((Supplier<R>)LinkedHashSet::new)));
        for (final T yt4 : this.available.values()) {
            if (yt4.isRequired() && !this.selected.contains(yt4)) {
                yt4.getDefaultPosition().insert((List<Object>)this.selected, yt4, Functions.identity(), false);
            }
        }
    }
    
    private void sortAvailable() {
        final List<Map.Entry<String, T>> list2 = Lists.newArrayList(this.available.entrySet());
        this.available.clear();
        final UnopenedPack unopenedPack;
        list2.stream().sorted(Map.Entry.<Comparable, Object>comparingByKey()).forEachOrdered(entry -> unopenedPack = this.available.put(entry.getKey(), (T)entry.getValue()));
    }
    
    public void setSelected(final Collection<T> collection) {
        this.selected.clear();
        this.selected.addAll(collection);
        for (final T yt4 : this.available.values()) {
            if (yt4.isRequired() && !this.selected.contains(yt4)) {
                yt4.getDefaultPosition().insert((List<Object>)this.selected, yt4, Functions.identity(), false);
            }
        }
    }
    
    public Collection<T> getAvailable() {
        return this.available.values();
    }
    
    public Collection<T> getUnselected() {
        final Collection<T> collection2 = Lists.newArrayList(this.available.values());
        collection2.removeAll(this.selected);
        return collection2;
    }
    
    public Collection<T> getSelected() {
        return this.selected;
    }
    
    @Nullable
    public T getPack(final String string) {
        return this.available.get(string);
    }
    
    public void addSource(final RepositorySource yr) {
        this.sources.add(yr);
    }
    
    @Override
    public void close() {
        this.available.values().forEach(UnopenedPack::close);
    }
}
