package net.minecraft.world.level.chunk.storage;

import it.unimi.dsi.fastutil.objects.ObjectIterator;
import net.minecraft.util.ExceptionCollector;
import java.io.DataOutputStream;
import java.io.DataOutput;
import javax.annotation.Nullable;
import java.io.DataInputStream;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.CompoundTag;
import java.io.IOException;
import net.minecraft.world.level.ChunkPos;
import java.io.File;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;

public final class RegionFileStorage implements AutoCloseable {
    private final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache;
    private final File folder;
    private final boolean sync;
    
    RegionFileStorage(final File file, final boolean boolean2) {
        this.regionCache = (Long2ObjectLinkedOpenHashMap<RegionFile>)new Long2ObjectLinkedOpenHashMap();
        this.folder = file;
        this.sync = boolean2;
    }
    
    private RegionFile getRegionFile(final ChunkPos bph) throws IOException {
        final long long3 = ChunkPos.asLong(bph.getRegionX(), bph.getRegionZ());
        final RegionFile cia5 = (RegionFile)this.regionCache.getAndMoveToFirst(long3);
        if (cia5 != null) {
            return cia5;
        }
        if (this.regionCache.size() >= 256) {
            ((RegionFile)this.regionCache.removeLast()).close();
        }
        if (!this.folder.exists()) {
            this.folder.mkdirs();
        }
        final File file6 = new File(this.folder, "r." + bph.getRegionX() + "." + bph.getRegionZ() + ".mca");
        final RegionFile cia6 = new RegionFile(file6, this.folder, this.sync);
        this.regionCache.putAndMoveToFirst(long3, cia6);
        return cia6;
    }
    
    @Nullable
    public CompoundTag read(final ChunkPos bph) throws IOException {
        final RegionFile cia3 = this.getRegionFile(bph);
        try (final DataInputStream dataInputStream4 = cia3.getChunkDataInputStream(bph)) {
            if (dataInputStream4 == null) {
                return null;
            }
            return NbtIo.read(dataInputStream4);
        }
    }
    
    protected void write(final ChunkPos bph, final CompoundTag le) throws IOException {
        final RegionFile cia4 = this.getRegionFile(bph);
        try (final DataOutputStream dataOutputStream5 = cia4.getChunkDataOutputStream(bph)) {
            NbtIo.write(le, dataOutputStream5);
        }
    }
    
    @Override
    public void close() throws IOException {
        final ExceptionCollector<IOException> adq2 = new ExceptionCollector<IOException>();
        for (final RegionFile cia4 : this.regionCache.values()) {
            try {
                cia4.close();
            }
            catch (IOException iOException5) {
                adq2.add(iOException5);
            }
        }
        adq2.throwIfPresent();
    }
    
    public void flush() throws IOException {
        for (final RegionFile cia3 : this.regionCache.values()) {
            cia3.flush();
        }
    }
}
