/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.LongBuffer;
import libcore.io.SizeOf;

/**
 * The {@code BitSet} class implements a
 * <a href="http://en.wikipedia.org/wiki/Bit_array">bit array</a>.
 * Each element is either true or false. A {@code BitSet} is created with a given size and grows
 * automatically if this size is exceeded.
 */
public class BitSet implements Serializable, Cloneable {
    private static final long serialVersionUID = 7997698588986878753L;

    private static final long ALL_ONES = ~0L;

    /**
     * The bits. Access bit n thus:
     *
     *   boolean bit = (bits[n / 64] | (1 << n)) != 0;
     *
     * Note that Java's shift operators truncate their rhs to the log2 size of the lhs.
     * That is, there's no "% 64" needed because it's implicit in the shift.
     *
     * TODO: would int[] be significantly more efficient for Android at the moment?
     */
    private long[] bits;

    /**
     * The number of elements of 'bits' that are actually in use (non-zero). Amongst other
     * things, this guarantees that isEmpty is cheap, because we never have to examine the array.
     */
    private transient int longCount;

    /**
     * Updates 'longCount' by inspecting 'bits'. Assumes that the new longCount is <= the current
     * longCount, to avoid scanning large tracts of empty array. This means it's safe to call
     * directly after a clear operation that may have cleared the highest set bit, but
     * not safe after an xor operation that may have cleared the highest set bit or
     * made a new highest set bit. In that case, you'd need to set 'longCount' to a conservative
     * estimate before calling this method.
     */
    private void shrinkSize() {
        int i = longCount - 1;
        while (i >= 0 && bits[i] == 0) {
            --i;
        }
        this.longCount = i + 1;
    }

    /**
     * Creates a new {@code BitSet} with size equal to 64 bits.
     */
    public BitSet() {
        this(new long[1]);
    }

    /**
     * Creates a new {@code BitSet} with size equal to {@code bitCount}, rounded up to
     * a multiple of 64.
     *
     * @throws NegativeArraySizeException if {@code bitCount < 0}.
     */
    public BitSet(int bitCount) {
        if (bitCount < 0) {
            throw new NegativeArraySizeException(Integer.toString(bitCount));
        }
        this.bits = arrayForBits(bitCount);
        this.longCount = 0;
    }

    private BitSet(long[] bits) {
        this.bits = bits;
        this.longCount = bits.length;
        shrinkSize();
    }

    private static long[] arrayForBits(int bitCount) {
        return new long[(bitCount + 63)/ 64];
    }

    @Override public Object clone() {
        try {
            BitSet clone = (BitSet) super.clone();
            clone.bits = bits.clone();
            clone.shrinkSize();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }
    }

    @Override public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof BitSet)) {
            return false;
        }
        BitSet lhs = (BitSet) o;
        if (this.longCount != lhs.longCount) {
            return false;
        }
        for (int i = 0; i < longCount; ++i) {
            if (bits[i] != lhs.bits[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Ensures that our long[] can hold at least 64 * desiredLongCount bits.
     */
    private void ensureCapacity(int desiredLongCount) {
        if (desiredLongCount <= bits.length) {
            return;
        }
        int newLength = Math.max(desiredLongCount, bits.length * 2);
        long[] newBits = new long[newLength];
        System.arraycopy(bits, 0, newBits, 0, longCount);
        this.bits = newBits;
        // 'longCount' is unchanged by this operation: the long[] is larger,
        // but you're not yet using any more of it.
    }

    @Override public int hashCode() {
        // The RI doesn't use Arrays.hashCode, and explicitly specifies this algorithm.
        long x = 1234;
        for (int i = 0; i < longCount; ++i) {
            x ^= bits[i] * (i + 1);
        }
        return (int) ((x >> 32) ^ x);
    }

    /**
     * Returns the bit at index {@code index}. Indexes greater than the current length return false.
     *
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public boolean get(int index) {
        if (index < 0) { // TODO: until we have an inlining JIT.
            checkIndex(index);
        }
        int arrayIndex = index / 64;
        if (arrayIndex >= longCount) {
            return false;
        }
        return (bits[arrayIndex] & (1L << index)) != 0;
    }

    /**
     * Sets the bit at index {@code index} to true.
     *
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public void set(int index) {
        if (index < 0) { // TODO: until we have an inlining JIT.
            checkIndex(index);
        }
        int arrayIndex = index / 64;
        if (arrayIndex >= bits.length) {
            ensureCapacity(arrayIndex + 1);
        }
        bits[arrayIndex] |= (1L << index);
        longCount = Math.max(longCount, arrayIndex + 1);
    }

    /**
     * Clears the bit at index {@code index}.
     *
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public void clear(int index) {
        if (index < 0) { // TODO: until we have an inlining JIT.
            checkIndex(index);
        }
        int arrayIndex = index / 64;
        if (arrayIndex >= longCount) {
            return;
        }
        bits[arrayIndex] &= ~(1L << index);
        shrinkSize();
    }

    /**
     * Flips the bit at index {@code index}.
     *
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public void flip(int index) {
        if (index < 0) { // TODO: until we have an inlining JIT.
            checkIndex(index);
        }
        int arrayIndex = index / 64;
        if (arrayIndex >= bits.length) {
            ensureCapacity(arrayIndex + 1);
        }
        bits[arrayIndex] ^= (1L << index);
        longCount = Math.max(longCount, arrayIndex + 1);
        shrinkSize();
    }

    private void checkIndex(int index) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("index < 0: " + index);
        }
    }

    private void checkRange(int fromIndex, int toIndex) {
        if ((fromIndex | toIndex) < 0 || toIndex < fromIndex) {
            throw new IndexOutOfBoundsException("fromIndex=" + fromIndex + " toIndex=" + toIndex);
        }
    }

    /**
     * Returns a new {@code BitSet} containing the
     * range of bits {@code [fromIndex, toIndex)}, shifted down so that the bit
     * at {@code fromIndex} is at bit 0 in the new {@code BitSet}.
     *
     * @throws IndexOutOfBoundsException
     *             if {@code fromIndex} or {@code toIndex} is negative, or if
     *             {@code toIndex} is smaller than {@code fromIndex}.
     */
    public BitSet get(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);

        int last = 64 * longCount;
        if (fromIndex >= last || fromIndex == toIndex) {
            return new BitSet(0);
        }
        if (toIndex > last) {
            toIndex = last;
        }

        int firstArrayIndex = fromIndex / 64;
        int lastArrayIndex = (toIndex - 1) / 64;
        long lowMask = ALL_ONES << fromIndex;
        long highMask = ALL_ONES >>> -toIndex;

        if (firstArrayIndex == lastArrayIndex) {
            long result = (bits[firstArrayIndex] & (lowMask & highMask)) >>> fromIndex;
            if (result == 0) {
                return new BitSet(0);
            }
            return new BitSet(new long[] { result });
        }

        long[] newBits = new long[lastArrayIndex - firstArrayIndex + 1];

        // first fill in the first and last indexes in the new BitSet
        newBits[0] = bits[firstArrayIndex] & lowMask;
        newBits[newBits.length - 1] = bits[lastArrayIndex] & highMask;

        // fill in the in between elements of the new BitSet
        for (int i = 1; i < lastArrayIndex - firstArrayIndex; i++) {
            newBits[i] = bits[firstArrayIndex + i];
        }

        // shift all the elements in the new BitSet to the right
        int numBitsToShift = fromIndex % 64;
        int actualLen = newBits.length;
        if (numBitsToShift != 0) {
            for (int i = 0; i < newBits.length; i++) {
                // shift the current element to the right regardless of
                // sign
                newBits[i] = newBits[i] >>> (numBitsToShift);

                // apply the last x bits of newBits[i+1] to the current
                // element
                if (i != newBits.length - 1) {
                    newBits[i] |= newBits[i + 1] << -numBitsToShift;
                }
                if (newBits[i] != 0) {
                    actualLen = i + 1;
                }
            }
        }
        return new BitSet(newBits);
    }

    /**
     * Sets the bit at index {@code index} to {@code state}.
     *
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public void set(int index, boolean state) {
        if (state) {
            set(index);
        } else {
            clear(index);
        }
    }

    /**
     * Sets the range of bits {@code [fromIndex, toIndex)} to {@code state}.
     *
     * @throws IndexOutOfBoundsException
     *             if {@code fromIndex} or {@code toIndex} is negative, or if
     *             {@code toIndex} is smaller than {@code fromIndex}.
     */
    public void set(int fromIndex, int toIndex, boolean state) {
        if (state) {
            set(fromIndex, toIndex);
        } else {
            clear(fromIndex, toIndex);
        }
    }

    /**
     * Clears all the bits in this {@code BitSet}. This method does not change the capacity.
     * Use {@code clear} if you want to reuse this {@code BitSet} with the same capacity, but
     * create a new {@code BitSet} if you're trying to potentially reclaim memory.
     */
    public void clear() {
        Arrays.fill(bits, 0, longCount, 0L);
        longCount = 0;
    }

    /**
     * Sets the range of bits {@code [fromIndex, toIndex)}.
     *
     * @throws IndexOutOfBoundsException
     *             if {@code fromIndex} or {@code toIndex} is negative, or if
     *             {@code toIndex} is smaller than {@code fromIndex}.
     */
    public void set(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);
        if (fromIndex == toIndex) {
            return;
        }
        int firstArrayIndex = fromIndex / 64;
        int lastArrayIndex = (toIndex - 1) / 64;
        if (lastArrayIndex >= bits.length) {
            ensureCapacity(lastArrayIndex + 1);
        }

        long lowMask = ALL_ONES << fromIndex;
        long highMask = ALL_ONES >>> -toIndex;
        if (firstArrayIndex == lastArrayIndex) {
            bits[firstArrayIndex] |= (lowMask & highMask);
        } else {
            int i = firstArrayIndex;
            bits[i++] |= lowMask;
            while (i < lastArrayIndex) {
                bits[i++] |= ALL_ONES;
            }
            bits[i++] |= highMask;
        }
        longCount = Math.max(longCount, lastArrayIndex + 1);
    }

    /**
     * Clears the range of bits {@code [fromIndex, toIndex)}.
     *
     * @throws IndexOutOfBoundsException
     *             if {@code fromIndex} or {@code toIndex} is negative, or if
     *             {@code toIndex} is smaller than {@code fromIndex}.
     */
    public void clear(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);
        if (fromIndex == toIndex || longCount == 0) {
            return;
        }
        int last = 64 * longCount;
        if (fromIndex >= last) {
            return;
        }
        if (toIndex > last) {
            toIndex = last;
        }
        int firstArrayIndex = fromIndex / 64;
        int lastArrayIndex = (toIndex - 1) / 64;

        long lowMask = ALL_ONES << fromIndex;
        long highMask = ALL_ONES >>> -toIndex;
        if (firstArrayIndex == lastArrayIndex) {
            bits[firstArrayIndex] &= ~(lowMask & highMask);
        } else {
            int i = firstArrayIndex;
            bits[i++] &= ~lowMask;
            while (i < lastArrayIndex) {
                bits[i++] = 0L;
            }
            bits[i++] &= ~highMask;
        }
        shrinkSize();
    }

    /**
     * Flips the range of bits {@code [fromIndex, toIndex)}.
     *
     * @throws IndexOutOfBoundsException
     *             if {@code fromIndex} or {@code toIndex} is negative, or if
     *             {@code toIndex} is smaller than {@code fromIndex}.
     */
    public void flip(int fromIndex, int toIndex) {
        checkRange(fromIndex, toIndex);
        if (fromIndex == toIndex) {
            return;
        }
        int firstArrayIndex = fromIndex / 64;
        int lastArrayIndex = (toIndex - 1) / 64;
        if (lastArrayIndex >= bits.length) {
            ensureCapacity(lastArrayIndex + 1);
        }

        long lowMask = ALL_ONES << fromIndex;
        long highMask = ALL_ONES >>> -toIndex;
        if (firstArrayIndex == lastArrayIndex) {
            bits[firstArrayIndex] ^= (lowMask & highMask);
        } else {
            int i = firstArrayIndex;
            bits[i++] ^= lowMask;
            while (i < lastArrayIndex) {
                bits[i++] ^= ALL_ONES;
            }
            bits[i++] ^= highMask;
        }
        longCount = Math.max(longCount, lastArrayIndex + 1);
        shrinkSize();
    }

    /**
     * Returns true if {@code this.and(bs)} is non-empty, but may be faster than computing that.
     */
    public boolean intersects(BitSet bs) {
        long[] bsBits = bs.bits;
        int length = Math.min(this.longCount, bs.longCount);
        for (int i = 0; i < length; ++i) {
            if ((bits[i] & bsBits[i]) != 0L) {
                return true;
            }
        }
        return false;
    }

    /**
     * Logically ands the bits of this {@code BitSet} with {@code bs}.
     */
    public void and(BitSet bs) {
        int minSize = Math.min(this.longCount, bs.longCount);
        for (int i = 0; i < minSize; ++i) {
            bits[i] &= bs.bits[i];
        }
        Arrays.fill(bits, minSize, longCount, 0L);
        shrinkSize();
    }

    /**
     * Clears all bits in this {@code BitSet} which are also set in {@code bs}.
     */
    public void andNot(BitSet bs) {
        int minSize = Math.min(this.longCount, bs.longCount);
        for (int i = 0; i < minSize; ++i) {
            bits[i] &= ~bs.bits[i];
        }
        shrinkSize();
    }

    /**
     * Logically ors the bits of this {@code BitSet} with {@code bs}.
     */
    public void or(BitSet bs) {
        int minSize = Math.min(this.longCount, bs.longCount);
        int maxSize = Math.max(this.longCount, bs.longCount);
        ensureCapacity(maxSize);
        for (int i = 0; i < minSize; ++i) {
            bits[i] |= bs.bits[i];
        }
        if (bs.longCount > minSize) {
            System.arraycopy(bs.bits, minSize, bits, minSize, maxSize - minSize);
        }
        longCount = maxSize;
    }

    /**
     * Logically xors the bits of this {@code BitSet} with {@code bs}.
     */
    public void xor(BitSet bs) {
        int minSize = Math.min(this.longCount, bs.longCount);
        int maxSize = Math.max(this.longCount, bs.longCount);
        ensureCapacity(maxSize);
        for (int i = 0; i < minSize; ++i) {
            bits[i] ^= bs.bits[i];
        }
        if (bs.longCount > minSize) {
            System.arraycopy(bs.bits, minSize, bits, minSize, maxSize - minSize);
        }
        longCount = maxSize;
        shrinkSize();
    }

    /**
     * Returns the capacity in bits of the array implementing this {@code BitSet}. This is
     * unrelated to the length of the {@code BitSet}, and not generally useful.
     * Use {@link #nextSetBit} to iterate, or {@link #length} to find the highest set bit.
     */
    public int size() {
        return bits.length * 64;
    }

    /**
     * Returns the number of bits up to and including the highest bit set. This is unrelated to
     * the {@link #size} of the {@code BitSet}.
     */
    public int length() {
        if (longCount == 0) {
            return 0;
        }
        return 64 * (longCount - 1) + (64 - Long.numberOfLeadingZeros(bits[longCount - 1]));
    }

    /**
     * Returns a string containing a concise, human-readable description of the
     * receiver: a comma-delimited list of the indexes of all set bits.
     * For example: {@code "{0,1,8}"}.
     */
    @Override public String toString() {
        //System.err.println("BitSet[longCount=" + longCount + ",bits=" + Arrays.toString(bits) + "]");
        StringBuilder sb = new StringBuilder(longCount / 2);
        sb.append('{');
        boolean comma = false;
        for (int i = 0; i < longCount; ++i) {
            if (bits[i] != 0) {
                for (int j = 0; j < 64; ++j) {
                    if ((bits[i] & 1L << j) != 0) {
                        if (comma) {
                            sb.append(", ");
                        } else {
                            comma = true;
                        }
                        sb.append(64 * i + j);
                    }
                }
            }
        }
        sb.append('}');
        return sb.toString();
    }

    /**
     * Returns the index of the first bit that is set on or after {@code index}, or -1
     * if no higher bits are set.
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public int nextSetBit(int index) {
        checkIndex(index);
        int arrayIndex = index / 64;
        if (arrayIndex >= longCount) {
            return -1;
        }
        long mask = ALL_ONES << index;
        if ((bits[arrayIndex] & mask) != 0) {
            return 64 * arrayIndex + Long.numberOfTrailingZeros(bits[arrayIndex] & mask);
        }
        while (++arrayIndex < longCount && bits[arrayIndex] == 0) {
        }
        if (arrayIndex == longCount) {
            return -1;
        }
        return 64 * arrayIndex + Long.numberOfTrailingZeros(bits[arrayIndex]);
    }

    /**
     * Returns the index of the first bit that is clear on or after {@code index}.
     * Since all bits past the end are implicitly clear, this never returns -1.
     * @throws IndexOutOfBoundsException if {@code index < 0}.
     */
    public int nextClearBit(int index) {
        checkIndex(index);
        int arrayIndex = index / 64;
        if (arrayIndex >= longCount) {
            return index;
        }
        long mask = ALL_ONES << index;
        if ((~bits[arrayIndex] & mask) != 0) {
            return 64 * arrayIndex + Long.numberOfTrailingZeros(~bits[arrayIndex] & mask);
        }
        while (++arrayIndex < longCount && bits[arrayIndex] == ALL_ONES) {
        }
        if (arrayIndex == longCount) {
            return 64 * longCount;
        }
        return 64 * arrayIndex + Long.numberOfTrailingZeros(~bits[arrayIndex]);
    }

    /**
     * Returns the index of the first bit that is set on or before {@code index}, or -1 if
     * no lower bits are set or {@code index == -1}.
     * @throws IndexOutOfBoundsException if {@code index < -1}.
     * @hide 1.7
     */
    public int previousSetBit(int index) {
        if (index == -1) {
            return -1;
        }
        checkIndex(index);
        // TODO: optimize this.
        for (int i = index; i >= 0; --i) {
            if (get(i)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns the index of the first bit that is clear on or before {@code index}, or -1 if
     * no lower bits are clear or {@code index == -1}.
     * @throws IndexOutOfBoundsException if {@code index < -1}.
     * @hide 1.7
     */
    public int previousClearBit(int index) {
        if (index == -1) {
            return -1;
        }
        checkIndex(index);
        // TODO: optimize this.
        for (int i = index; i >= 0; --i) {
            if (!get(i)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns true if all the bits in this {@code BitSet} are set to false, false otherwise.
     */
    public boolean isEmpty() {
        return (longCount == 0);
    }

    /**
     * Returns the number of bits that are {@code true} in this {@code BitSet}.
     */
    public int cardinality() {
        int result = 0;
        for (int i = 0; i < longCount; ++i) {
            result += Long.bitCount(bits[i]);
        }
        return result;
    }

    /**
     * Equivalent to {@code BitSet.valueOf(LongBuffer.wrap(longs))}, but likely to be faster.
     * This is likely to be the fastest way to create a {@code BitSet} because it's closest
     * to the internal representation.
     * @hide 1.7
     */
    public static BitSet valueOf(long[] longs) {
        return new BitSet(longs.clone());
    }

    /**
     * Returns a {@code BitSet} corresponding to {@code longBuffer}, interpreted as a little-endian
     * sequence of bits. This method does not alter the {@code LongBuffer}.
     * @hide 1.7
     */
    public static BitSet valueOf(LongBuffer longBuffer) {
        // The bulk get would mutate LongBuffer (even if we reset position later), and it's not
        // clear that's allowed. My assumption is that it's the long[] variant that's the common
        // case anyway, so copy the buffer into a long[].
        long[] longs = new long[longBuffer.remaining()];
        for (int i = 0; i < longs.length; ++i) {
            longs[i] = longBuffer.get(longBuffer.position() + i);
        }
        return BitSet.valueOf(longs);
    }

    /**
     * Equivalent to {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}.
     * @hide 1.7
     */
    public static BitSet valueOf(byte[] bytes) {
        return BitSet.valueOf(ByteBuffer.wrap(bytes));
    }

    /**
     * Returns a {@code BitSet} corresponding to {@code byteBuffer}, interpreted as a little-endian
     * sequence of bits. This method does not alter the {@code ByteBuffer}.
     * @hide 1.7
     */
    public static BitSet valueOf(ByteBuffer byteBuffer) {
        byteBuffer = byteBuffer.slice().order(ByteOrder.LITTLE_ENDIAN);
        long[] longs = arrayForBits(byteBuffer.remaining() * 8);
        int i = 0;
        while (byteBuffer.remaining() >= SizeOf.LONG) {
            longs[i++] = byteBuffer.getLong();
        }
        for (int j = 0; byteBuffer.hasRemaining(); ++j) {
            longs[i] |= ((((long) byteBuffer.get()) & 0xff) << (8*j));
        }
        return BitSet.valueOf(longs);
    }

    /**
     * Returns a new {@code long[]} containing a little-endian representation of the bits of
     * this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
     * this {@code BitSet}.
     * @hide 1.7
     */
    public long[] toLongArray() {
        return Arrays.copyOf(bits, longCount);
    }

    /**
     * Returns a new {@code byte[]} containing a little-endian representation the bits of
     * this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
     * this {@code BitSet}.
     * @hide 1.7
     */
    public byte[] toByteArray() {
        int bitCount = length();
        byte[] result = new byte[(bitCount + 7)/ 8];
        for (int i = 0; i < result.length; ++i) {
            int lowBit = 8 * i;
            int arrayIndex = lowBit / 64;
            result[i] = (byte) (bits[arrayIndex] >>> lowBit);
        }
        return result;
    }

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        // The serialized form doesn't include a 'longCount' field, so we'll have to scan the array.
        this.longCount = this.bits.length;
        shrinkSize();
    }
}
