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

package com.google.protobuf;

import java.util.Arrays;
import java.util.RandomAccess;

final class ProtobufArrayList<E> extends AbstractProtobufList<E> implements RandomAccess
{
    private static final Object[] EMPTY_ARRAY;
    private static final ProtobufArrayList<Object> EMPTY_LIST;
    private E[] array;
    private int size;
    
    public static <E> ProtobufArrayList<E> emptyList() {
        return (ProtobufArrayList<E>)ProtobufArrayList.EMPTY_LIST;
    }
    
    ProtobufArrayList() {
        this(ProtobufArrayList.EMPTY_ARRAY, 0, true);
    }
    
    private ProtobufArrayList(final E[] array, final int size, final boolean isMutable) {
        super(isMutable);
        this.array = array;
        this.size = size;
    }
    
    @Override
    public ProtobufArrayList<E> mutableCopyWithCapacity(final int capacity) {
        if (capacity < this.size) {
            throw new IllegalArgumentException();
        }
        final E[] newArray = (E[])((capacity == 0) ? ProtobufArrayList.EMPTY_ARRAY : Arrays.copyOf(this.array, capacity));
        return new ProtobufArrayList<E>(newArray, this.size, true);
    }
    
    @Override
    public boolean add(final E element) {
        this.ensureIsMutable();
        if (this.size == this.array.length) {
            final int length = growSize(this.array.length);
            final E[] newArray = Arrays.copyOf(this.array, length);
            this.array = newArray;
        }
        this.array[this.size++] = element;
        ++this.modCount;
        return true;
    }
    
    private static int growSize(final int previousSize) {
        return Math.max(previousSize * 3 / 2 + 1, 10);
    }
    
    @Override
    public void add(final int index, final E element) {
        this.ensureIsMutable();
        if (index < 0 || index > this.size) {
            throw new IndexOutOfBoundsException(this.makeOutOfBoundsExceptionMessage(index));
        }
        if (this.size < this.array.length) {
            System.arraycopy(this.array, index, this.array, index + 1, this.size - index);
        }
        else {
            final int length = growSize(this.array.length);
            final E[] newArray = createArray(length);
            System.arraycopy(this.array, 0, newArray, 0, index);
            System.arraycopy(this.array, index, newArray, index + 1, this.size - index);
            this.array = newArray;
        }
        this.array[index] = element;
        ++this.size;
        ++this.modCount;
    }
    
    @Override
    public E get(final int index) {
        this.ensureIndexInRange(index);
        return this.array[index];
    }
    
    @Override
    public E remove(final int index) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final E value = this.array[index];
        if (index < this.size - 1) {
            System.arraycopy(this.array, index + 1, this.array, index, this.size - index - 1);
        }
        --this.size;
        ++this.modCount;
        return value;
    }
    
    @Override
    public E set(final int index, final E element) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final E toReturn = this.array[index];
        this.array[index] = element;
        ++this.modCount;
        return toReturn;
    }
    
    @Override
    public int size() {
        return this.size;
    }
    
    void ensureCapacity(final int minCapacity) {
        if (minCapacity <= this.array.length) {
            return;
        }
        if (this.array.length == 0) {
            this.array = (E[])new Object[Math.max(minCapacity, 10)];
            return;
        }
        int n;
        for (n = this.array.length; n < minCapacity; n = growSize(n)) {}
        this.array = Arrays.copyOf(this.array, n);
    }
    
    private static <E> E[] createArray(final int capacity) {
        return (E[])new Object[capacity];
    }
    
    private void ensureIndexInRange(final int index) {
        if (index < 0 || index >= this.size) {
            throw new IndexOutOfBoundsException(this.makeOutOfBoundsExceptionMessage(index));
        }
    }
    
    private String makeOutOfBoundsExceptionMessage(final int index) {
        return "Index:" + index + ", Size:" + this.size;
    }
    
    static {
        EMPTY_ARRAY = new Object[0];
        EMPTY_LIST = new ProtobufArrayList<Object>(ProtobufArrayList.EMPTY_ARRAY, 0, false);
    }
}
