// 
// Decompiled by Procyon v0.6.0
// 

package it.unimi.dsi.fastutil.shorts;

import java.util.Arrays;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.ShortBuffer;

public class ShortMappedBigList extends AbstractShortBigList
{
    public static int LOG2_BYTES;
    @Deprecated
    public static int LOG2_BITS;
    private static int CHUNK_SHIFT;
    public static final long CHUNK_SIZE;
    private static final long CHUNK_MASK;
    private final ShortBuffer[] buffer;
    private final boolean[] readyToUse;
    private final int n;
    private final long size;
    
    protected ShortMappedBigList(final ShortBuffer[] buffer, final long size, final boolean[] readyToUse) {
        this.buffer = buffer;
        this.n = buffer.length;
        this.size = size;
        this.readyToUse = readyToUse;
        for (int i = 0; i < this.n; ++i) {
            if (i < this.n - 1 && buffer[i].capacity() != ShortMappedBigList.CHUNK_SIZE) {
                throw new IllegalArgumentException();
            }
        }
    }
    
    public static ShortMappedBigList map(final FileChannel fileChannel) throws IOException {
        return map(fileChannel, ByteOrder.BIG_ENDIAN);
    }
    
    public static ShortMappedBigList map(final FileChannel fileChannel, final ByteOrder byteOrder) throws IOException {
        return map(fileChannel, byteOrder, FileChannel.MapMode.READ_ONLY);
    }
    
    public static ShortMappedBigList map(final FileChannel fileChannel, final ByteOrder byteOrder, final FileChannel.MapMode mapMode) throws IOException {
        final long size = fileChannel.size() / 2L;
        final int chunks = (int)((size + (ShortMappedBigList.CHUNK_SIZE - 1L)) / ShortMappedBigList.CHUNK_SIZE);
        final ShortBuffer[] buffer = new ShortBuffer[chunks];
        for (int i = 0; i < chunks; ++i) {
            buffer[i] = fileChannel.map(mapMode, i * ShortMappedBigList.CHUNK_SIZE * 2L, Math.min(ShortMappedBigList.CHUNK_SIZE, size - i * ShortMappedBigList.CHUNK_SIZE) * 2L).order(byteOrder).asShortBuffer();
        }
        final boolean[] readyToUse = new boolean[chunks];
        Arrays.fill(readyToUse, true);
        return new ShortMappedBigList(buffer, size, readyToUse);
    }
    
    private ShortBuffer ShortBuffer(final int n) {
        if (this.readyToUse[n]) {
            return this.buffer[n];
        }
        this.readyToUse[n] = true;
        return this.buffer[n] = this.buffer[n].duplicate();
    }
    
    public ShortMappedBigList copy() {
        return new ShortMappedBigList(this.buffer.clone(), this.size, new boolean[this.n]);
    }
    
    @Override
    public short getShort(final long index) {
        return this.ShortBuffer((int)(index >>> ShortMappedBigList.CHUNK_SHIFT)).get((int)(index & ShortMappedBigList.CHUNK_MASK));
    }
    
    @Override
    public void getElements(final long from, final short[] a, int offset, int length) {
        int chunk = (int)(from >>> ShortMappedBigList.CHUNK_SHIFT);
        int displ = (int)(from & ShortMappedBigList.CHUNK_MASK);
        while (length > 0) {
            final ShortBuffer b = this.ShortBuffer(chunk);
            final int l = Math.min(b.capacity() - displ, length);
            if (l == 0) {
                throw new ArrayIndexOutOfBoundsException();
            }
            b.position();
            b.get(a, offset, l);
            if ((displ += l) == ShortMappedBigList.CHUNK_SIZE) {
                displ = 0;
                ++chunk;
            }
            offset += l;
            length -= l;
        }
    }
    
    @Override
    public short set(final long index, final short value) {
        final ShortBuffer b = this.ShortBuffer((int)(index >>> ShortMappedBigList.CHUNK_SHIFT));
        final int i = (int)(index & ShortMappedBigList.CHUNK_MASK);
        final short previousValue = b.get(i);
        b.put(i, value);
        return previousValue;
    }
    
    @Override
    public long size64() {
        return this.size;
    }
    
    static {
        ShortMappedBigList.LOG2_BYTES = 63 - Long.numberOfLeadingZeros(2L);
        ShortMappedBigList.LOG2_BITS = 63 - Long.numberOfLeadingZeros(2L);
        ShortMappedBigList.CHUNK_SHIFT = 30 - ShortMappedBigList.LOG2_BYTES;
        CHUNK_SIZE = 1L << ShortMappedBigList.CHUNK_SHIFT;
        CHUNK_MASK = ShortMappedBigList.CHUNK_SIZE - 1L;
    }
}
