package net.minecraft.server.packs.repository;

import net.minecraft.server.packs.PackResources;
import javax.annotation.Nullable;
import java.util.function.Predicate;
import java.util.Objects;
import java.util.stream.Stream;
import com.google.common.base.Functions;
import java.util.stream.Collectors;
import java.util.Iterator;
import com.google.common.collect.Maps;
import java.util.Collection;
import java.util.stream.Collector;
import java.util.function.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class PackRepository<T extends Pack> implements AutoCloseable {
    private final Set<RepositorySource> sources;
    private Map<String, T> available;
    private List<T> selected;
    private final Pack.PackConstructor<T> constructor;
    
    public PackRepository(final Pack.PackConstructor<T> a, final RepositorySource... arr) {
        this.available = ImmutableMap.of();
        this.selected = ImmutableList.of();
        this.constructor = a;
        this.sources = ImmutableSet.<RepositorySource>copyOf(arr);
    }
    
    public void reload() {
        final List<String> list2 = this.selected.stream().map(Pack::getId).collect(ImmutableList.toImmutableList());
        this.close();
        this.available = this.discoverAvailable();
        this.selected = this.rebuildSelected(list2);
    }
    
    private Map<String, T> discoverAvailable() {
        final Map<String, T> map2 = Maps.newTreeMap();
        for (final RepositorySource aat4 : this.sources) {
            final Pack pack;
            aat4.<T>loadPacks(aap -> pack = map2.put(aap.getId(), (T)aap), this.constructor);
        }
        return ImmutableMap.copyOf(map2);
    }
    
    public void setSelected(final Collection<String> collection) {
        this.selected = this.rebuildSelected(collection);
    }
    
    private List<T> rebuildSelected(final Collection<String> collection) {
        final List<T> list3 = this.getAvailablePacks(collection).collect(Collectors.toList());
        for (final T aap5 : this.available.values()) {
            if (aap5.isRequired() && !list3.contains(aap5)) {
                aap5.getDefaultPosition().insert((List<Object>)list3, aap5, Functions.identity(), false);
            }
        }
        return ImmutableList.copyOf(list3);
    }
    
    private Stream<T> getAvailablePacks(final Collection<String> collection) {
        return collection.stream().<T>map(this.available::get).filter(Objects::nonNull);
    }
    
    public Collection<String> getAvailableIds() {
        return this.available.keySet();
    }
    
    public Collection<T> getAvailablePacks() {
        return this.available.values();
    }
    
    public Collection<String> getSelectedIds() {
        return this.selected.stream().map(Pack::getId).collect(ImmutableSet.toImmutableSet());
    }
    
    public Collection<T> getSelectedPacks() {
        return this.selected;
    }
    
    @Nullable
    public T getPack(final String string) {
        return this.available.get(string);
    }
    
    @Override
    public void close() {
        this.available.values().forEach(Pack::close);
    }
    
    public boolean isAvailable(final String string) {
        return this.available.containsKey(string);
    }
    
    public List<PackResources> openAllSelected() {
        return this.selected.stream().map(Pack::open).collect(ImmutableList.toImmutableList());
    }
}
