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

package com.google.protobuf;

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

final class LongArrayList extends AbstractProtobufList<Long> implements Internal.LongList, RandomAccess, PrimitiveNonBoxingCollection
{
    private static final long[] EMPTY_ARRAY;
    private static final LongArrayList EMPTY_LIST;
    private long[] array;
    private int size;
    
    public static LongArrayList emptyList() {
        return LongArrayList.EMPTY_LIST;
    }
    
    LongArrayList() {
        this(LongArrayList.EMPTY_ARRAY, 0, true);
    }
    
    private LongArrayList(final long[] other, final int size, final boolean isMutable) {
        super(isMutable);
        this.array = other;
        this.size = size;
    }
    
    LongArrayList(final LongArrayList other, final boolean isMutable) {
        this((other.size == 0) ? LongArrayList.EMPTY_ARRAY : Arrays.copyOf(other.array, other.size), other.size, isMutable);
    }
    
    @Override
    protected void removeRange(final int fromIndex, final int toIndex) {
        this.ensureIsMutable();
        if (toIndex < fromIndex) {
            throw new IndexOutOfBoundsException("toIndex < fromIndex");
        }
        System.arraycopy(this.array, toIndex, this.array, fromIndex, this.size - toIndex);
        this.size -= toIndex - fromIndex;
        ++this.modCount;
    }
    
    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof LongArrayList)) {
            return super.equals(o);
        }
        final LongArrayList other = (LongArrayList)o;
        if (this.size != other.size) {
            return false;
        }
        final long[] arr = other.array;
        for (int i = 0; i < this.size; ++i) {
            if (this.array[i] != arr[i]) {
                return false;
            }
        }
        return true;
    }
    
    @Override
    public int hashCode() {
        int result = 1;
        for (int i = 0; i < this.size; ++i) {
            result = 31 * result + Internal.hashLong(this.array[i]);
        }
        return result;
    }
    
    @Override
    public Internal.LongList mutableCopyWithCapacity(final int capacity) {
        if (capacity < this.size) {
            throw new IllegalArgumentException();
        }
        final long[] newArray = (capacity == 0) ? LongArrayList.EMPTY_ARRAY : Arrays.copyOf(this.array, capacity);
        return new LongArrayList(newArray, this.size, true);
    }
    
    @Override
    public Long get(final int index) {
        return this.getLong(index);
    }
    
    @Override
    public long getLong(final int index) {
        this.ensureIndexInRange(index);
        return this.array[index];
    }
    
    @Override
    public int indexOf(final Object element) {
        if (!(element instanceof Long)) {
            return -1;
        }
        final long unboxedElement = (long)element;
        for (int numElems = this.size(), i = 0; i < numElems; ++i) {
            if (this.array[i] == unboxedElement) {
                return i;
            }
        }
        return -1;
    }
    
    @Override
    public boolean contains(final Object element) {
        return this.indexOf(element) != -1;
    }
    
    @Override
    public int size() {
        return this.size;
    }
    
    @Override
    public Long set(final int index, final Long element) {
        return this.setLong(index, element);
    }
    
    @Override
    public long setLong(final int index, final long element) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final long previousValue = this.array[index];
        this.array[index] = element;
        return previousValue;
    }
    
    @Override
    public boolean add(final Long element) {
        this.addLong(element);
        return true;
    }
    
    @Override
    public void add(final int index, final Long element) {
        this.addLong(index, element);
    }
    
    @Override
    public void addLong(final long element) {
        this.ensureIsMutable();
        if (this.size == this.array.length) {
            final int length = growSize(this.array.length);
            final long[] newArray = new long[length];
            System.arraycopy(this.array, 0, newArray, 0, this.size);
            this.array = newArray;
        }
        this.array[this.size++] = element;
    }
    
    private void addLong(final int index, final long 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 long[] newArray = new long[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 boolean addAll(final Collection<? extends Long> collection) {
        this.ensureIsMutable();
        Internal.checkNotNull(collection);
        if (!(collection instanceof LongArrayList)) {
            return super.addAll(collection);
        }
        final LongArrayList list = (LongArrayList)collection;
        if (list.size == 0) {
            return false;
        }
        final int overflow = Integer.MAX_VALUE - this.size;
        if (overflow < list.size) {
            throw new OutOfMemoryError();
        }
        final int newSize = this.size + list.size;
        if (newSize > this.array.length) {
            this.array = Arrays.copyOf(this.array, newSize);
        }
        System.arraycopy(list.array, 0, this.array, this.size, list.size);
        this.size = newSize;
        ++this.modCount;
        return true;
    }
    
    @Override
    public Long remove(final int index) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final long 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;
    }
    
    void ensureCapacity(final int minCapacity) {
        if (minCapacity <= this.array.length) {
            return;
        }
        if (this.array.length == 0) {
            this.array = new long[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 int growSize(final int previousSize) {
        return Math.max(previousSize * 3 / 2 + 1, 10);
    }
    
    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 long[0];
        EMPTY_LIST = new LongArrayList(LongArrayList.EMPTY_ARRAY, 0, false);
    }
}
