package net.minecraft.client.sounds;

import java.util.Iterator;
import java.util.function.Predicate;
import java.util.Objects;
import java.util.stream.Stream;
import java.util.function.Consumer;
import com.mojang.blaze3d.audio.Channel;
import com.google.common.collect.Sets;
import java.util.concurrent.Executor;
import com.mojang.blaze3d.audio.Library;
import java.util.Set;

public class ChannelAccess {
    private final Set<ChannelHandle> channels;
    private final Library library;
    private final Executor executor;
    
    public ChannelAccess(final Library cwt, final Executor executor) {
        this.channels = Sets.<ChannelHandle>newIdentityHashSet();
        this.library = cwt;
        this.executor = executor;
    }
    
    public ChannelHandle createHandle(final Library.Pool c) {
        final ChannelHandle a3 = new ChannelHandle();
        final Channel cws4;
        final ChannelHandle a4;
        this.executor.execute(() -> {
            cws4 = this.library.acquireChannel(c);
            if (cws4 != null) {
                a4.channel = cws4;
                this.channels.add(a4);
            }
            return;
        });
        return a3;
    }
    
    public void executeOnChannels(final Consumer<Stream<Channel>> consumer) {
        this.executor.execute(() -> consumer.accept(this.channels.stream().<Channel>map(a -> a.channel).filter(Objects::nonNull)));
    }
    
    public void scheduleTick() {
        final Iterator<ChannelHandle> iterator2;
        ChannelHandle a3;
        this.executor.execute(() -> {
            iterator2 = this.channels.iterator();
            while (iterator2.hasNext()) {
                a3 = iterator2.next();
                a3.channel.updateStream();
                if (a3.channel.stopped()) {
                    a3.release();
                    iterator2.remove();
                }
            }
        });
    }
    
    public void clear() {
        this.channels.forEach(ChannelHandle::release);
        this.channels.clear();
    }
    
    public class ChannelHandle {
        private Channel channel;
        private boolean stopped;
        
        public boolean isStopped() {
            return this.stopped;
        }
        
        public void execute(final Consumer<Channel> consumer) {
            ChannelAccess.this.executor.execute(() -> {
                if (this.channel != null) {
                    consumer.accept(this.channel);
                }
            });
        }
        
        public void release() {
            this.stopped = true;
            ChannelAccess.this.library.releaseChannel(this.channel);
            this.channel = null;
        }
    }
}
