/**
 * A BitSet similar to java.util.BitSet.
 *
 * <p>JavaScript Note: There is no good way to implement something like this in 
 * JavaScript.  JS has no true int type, arrays are usually implemented as
 * hashes, etc.  This class should probably be nixed for something that is
 * similarly (in)efficient, but more clear.</p>
 *
 * @class
 * @param {Number|Array} [bits] a 32 bit number or array of 32 bit numbers
 *                              representing the bitset.  These are typically
 *                              generated by the ANTLR Tool.
 */
org.antlr.runtime.BitSet = function(bits) {
    if (!bits) {
        bits = org.antlr.runtime.BitSet.BITS;
    }

    if (org.antlr.lang.isArray(bits)) {
        /**
         * An array of Numbers representing the BitSet.
         * @type Array
         */
        this.bits = bits;
    } else if(org.antlr.lang.isNumber(bits)) {
        this.bits = [];
    }
};

org.antlr.lang.augmentObject(org.antlr.runtime.BitSet, {
    /**
     * Number of bits in each number.
     * @constant
     * @memberOf org.antlr.runtime.BitSet
     */
    BITS: 32,

    /**
     * Log (base 2) of the number of bits in each number.
     * @constant
     * @memberOf org.antlr.runtime.BitSet
     */
    LOG_BITS: 5,  // 2^5 == 32 

    /**
     * We will often need to do a mod operator (i mod nbits).  Its
     * turns out that, for powers of two, this mod operation is
     * same as (i & (nbits-1)).  Since mod is slow, we use a
     * precomputed mod mask to do the mod instead.
     * @constant
     * @memberOf org.antlr.runtime.BitSet
     */
    MOD_MASK: 31, // BITS - 1

    /**
     * Create mask for bit modded to fit in a single word.
     * @example
     * bitmask(35) => 00000000000000000000000000000100
     * bitmask(3)  => 00000000000000000000000000000100
     * @param {Number} bitNumber the bit to create a mask for.
     * @returns {Number} the bitmask.
     * @memberOf org.antlr.runtime.BitSet
     * @private
     */
    bitMask: function(bitNumber) {
        var bitPosition = bitNumber & org.antlr.runtime.BitSet.MOD_MASK;
        return 1 << bitPosition;
    },

    /**
     * Calculate the minimum number of bits needed to represent el.
     * @param {Number} el a number to be included in the BitSet.
     * @returns {Number} the number of bits need to create a BitSet with member
     *                   el.
     * @memberOf org.antlr.runtime.BitSet
     * @private
     */
    numWordsToHold: function(el) {
        return (el >> org.antlr.runtime.BitSet.LOG_BITS) + 1;
    },

    /**
     * @param {Number} bit a number to be included in the BitSet
     * @returns {Number} the index of the word in the field bits that would
     *                   hold bit.
     * @memberOf org.antlr.runtime.BitSet
     * @private
     */
    wordNumber: function(bit) {
        return bit >> org.antlr.runtime.BitSet.LOG_BITS; // bit / BITS
    },

    /**
     * BitSet factory method.
     * 
     * <p>Operates in a number of modes:
     * <ul>
     * <li>If el is a number create the BitSet containing that number.</li>
     * <li>If el is an array create the BitSet containing each number in the
     * array.</li>
     * <li>If el is a BitSet return el.</li>
     * <li>If el is an Object create the BitSet containing each numeric value
     * in el.</li>
     * <li>If el is a number and el2 is a number return a BitSet containing
     * the numbers between el and el2 (inclusive).</li>
     * </ul>
     * </p>
     * @param {Number|Array|org.antlr.runtime.BitSet|Object} el
     * @param {Number} el2
     * @returns {org.antlr.runtime.BitSet}
     * @memberOf org.antlr.runtime.BitSet
     */
    of: function(el, el2) {
        var i, n, s, keys;

        if (org.antlr.lang.isNumber(el)) {
            if (org.antlr.lang.isNumber(el2)) {
                s = new org.antlr.runtime.BitSet(el2 + 1);
                for (i = el; i <= el2; i++) {
                    n = org.antlr.runtime.BitSet.wordNumber(i);
                    s.bits[n] |= org.antlr.runtime.BitSet.bitMask(i);
                }
                return s;
            } else {
                s = new org.antlr.runtime.BitSet(el + 1);
                s.add(el);
                return s;
            }
        } else if(org.antlr.lang.isArray(el)) {
            s = new org.antlr.runtime.BitSet();
            for (i=el.length-1; i>=0; i--) {
                s.add(el[i]);
            }
            return s;
        } else if (el instanceof org.antlr.runtime.BitSet) {
            if (!el) {
                return null;
            }
            return el;
        } else if (el instanceof org.antlr.runtime.IntervalSet) {
            if (!el) {
                return null;
            }
            s = new org.antlr.runtime.BitSet();
            s.addAll(el);
            return s;
        } else if (org.antlr.lang.isObject(el)) {
            keys = [];
            for (i in el) {
                if (org.antlr.lang.isNumber(i)) {
                    keys.push(i);
                }
            }
            return org.antlr.runtime.BitSet.of(keys);
        }
    }
});



org.antlr.runtime.BitSet.prototype = {
    /**
     * Add el into this set.
     * @param {Number} el the number to add to the set.
     */
    add: function(el) {
        var n = org.antlr.runtime.BitSet.wordNumber(el);
        if (n >= this.bits.length) {
            this.growToInclude(el);
        }
        this.bits[n] |= org.antlr.runtime.BitSet.bitMask(el);
    },

    /**
     * Add multiple elements into this set.
     * @param {Array|org.antlr.runtime.BitSet} elements the elements to be added to
     *                                           this set.
     */
    addAll: function(elements) {
        var other,
            i,
            e;

        if ( elements instanceof org.antlr.runtime.BitSet ) {
            this.orInPlace(elements);
        }
		else if ( elements instanceof org.antlr.runtime.IntervalSet ) {
			other = elements;
			// walk set and add each interval
            /* @todo after implementing intervalset
			for (Iterator iter = other.intervals.iterator(); iter.hasNext();) {
				Interval I = (Interval) iter.next();
				this.orInPlace(BitSet.range(I.a,I.b));
			}*/
		} else if (org.antlr.lang.isArray(elements)) {
    		for (i = 0; i < elements.length; i++) {
	    		e = elements[i];
		    	this.add(e);
    		}
        } else {
            return;
        }
	},

    /**
     * Clone this BitSet and then {@link #andInPlace} with a.
     * @param {org.antlr.runtime.BitSet} a a bit set.
     * @returns {org.antlr.runtime.BitSet}
     */
    and: function(a) {
        var s = this.clone();
        s.andInPlace(a);
        return s;
    },

    /**
     * Perform a logical AND of this target BitSet with the argument BitSet.
     *
     * This bit set is modified so that each bit in it has the value true if 
     * and only if it both initially had the value true and the corresponding 
     * bit in the bit set argument also had the value true. 
     * @param {org.antlr.runtime.BitSet} a a bit set.
     * @returns {org.antlr.runtime.BitSet}
     */
    andInPlace: function(a) {
        var min = Math.min(this.bits.length, a.bits.length),
            i;
        for (i = min - 1; i >= 0; i--) {
            this.bits[i] &= a.bits[i];
        }
        // clear all bits in this not present in a (if this bigger than a).
        for (i = min; i < this.bits.length; i++) {
            this.bits[i] = 0;
        }
    },

    /**
     * Clear all bits or a specific bit.
     *
     * If no arguments given, sets all of the bits in this BitSet to false.
     * If one argument given, sets the bit specified by the index to false.
     * @param {Number} [el] the index of the bit to be cleared.
     */
    clear: function(el) {
        if (arguments.length===0) {
            var i;
            for (i = this.bits.length - 1; i >= 0; i--) {
                this.bits[i] = 0;
            }
            return;
        }

        var n = org.antlr.runtime.BitSet.wordNumber(el);
        if (n >= this.bits.length) {	// grow as necessary to accommodate
            this.growToInclude(el);
        }
        this.bits[n] &= ~org.antlr.runtime.BitSet.bitMask(el);
    },

    /**
     * Cloning this BitSet produces a new BitSet  that is equal to it. 
     *
     * The clone of the bit set is another bit set that has exactly the same
     * bit set to true as this bit set. 
     * @returns {org.antlr.runtime.BitSet} a clone of this BitSet.
     */
    clone: function() {
        var i, len, b=[];
        for (i=0, len=this.bits.length; i<len; i++) {
            b[i] = this.bits[i];
        }
        return new org.antlr.runtime.BitSet(b);
    },

    /**
     * Returns the number of bits of space actually in use by this BitSet to 
     * represent bit values.
     *
     * The maximum element in the set is the size - 1st element. 
     * @returns {Number} the number of bits currently in this bit set.
     */
    size: function() {
        var deg = 0, i, word, bit;
        for (i = this.bits.length - 1; i >= 0; i--) {
            word = this.bits[i];
            if (word !== 0) {
                for (bit = org.antlr.runtime.BitSet.BITS - 1; bit >= 0; bit--) {
                    if ((word & (1 << bit)) !== 0) {
                        deg++;
                    }
                }
            }
        }
        return deg;
    },

    /**
     * Compares this object against the specified object.
     *
     * The result is true if and only if the argument is not null and is a
     * BitSet object that has exactly the same set of bits set to true as
     * this bit set. That is, for every nonnegative int index k,
     * <pre><code>
     * ((BitSet)obj).get(k) == this.get(k)
     * </code></pre>
     * must be true. The current sizes of the two bit sets are not compared.
     * @param {Object} other the object to compare with.
     * @returns {Boolean} if the objects are the same; false otherwise.
     */
    equals: function(other) {
        if ( !other || !(other instanceof org.antlr.runtime.BitSet) ) {
            return false;
        }

        var otherSet = other,
            i,
            n = Math.min(this.bits.length, otherSet.bits.length);

        // for any bits in common, compare
        for (i=0; i<n; i++) {
            if (this.bits[i] != otherSet.bits[i]) {
                return false;
            }
        }

        // make sure any extra bits are off

        if (this.bits.length > n) {
            for (i = n+1; i<this.bits.length; i++) {
                if (this.bits[i] !== 0) {
                    return false;
                }
            }
        }
        else if (otherSet.bits.length > n) {
            for (i = n+1; i<otherSet.bits.length; i++) {
                if (otherSet.bits[i] !== 0) {
                    return false;
                }
            }
        }

        return true;
    },

    /**
     * Grows the set to a larger number of bits.
     * @param {Number} bit element that must fit in set
     * @private
     */
    growToInclude: function(bit) {
        var newSize = Math.max(this.bits.length << 1, org.antlr.runtime.BitSet.numWordsToHold(bit)),
            newbits = [], //new Array(newSize),
            i,
            len;
        for (i=0, len=this.bits.length; i<len; i++) {
            newbits[i] = this.bits[i];
        }
        this.bits = newbits;
    },

    /**
     * Returns the value of the bit with the specified index.
     *
     * The value is true if the bit with the index el is currently set 
     * in this BitSet; otherwise, the result is false.
     * @param {Number} el the bit index.
     * @returns {Boolean} the value of the bit with the specified index.
     */
    member: function(el) {
        var n = org.antlr.runtime.BitSet.wordNumber(el);
        if (n >= this.bits.length) { return false; }
        return (this.bits[n] & org.antlr.runtime.BitSet.bitMask(el)) !== 0;
    },

    /**
     * Returns the index of the first bit that is set to true.
     * If no such bit exists then -1 is returned.
     * @returns {Number} the index of the next set bit.
     */
    getSingleElement: function() {
        var i;
        for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) {
            if (this.member(i)) {
                return i;
            }
        }
        return -1; //Label.INVALID;
    },

    /**
     * Returns true if this BitSet contains no bits that are set to true.
     * @returns {Boolean} boolean indicating whether this BitSet is empty.
     */
    isNil: function() {
        var i;
        for (i = this.bits.length - 1; i >= 0; i--) {
            if (this.bits[i] !== 0) {
                return false;
            }
        }
        return true;
    },

    /**
     * If a bit set argument is passed performs a {@link #subtract} of this bit
     * set with the argument bit set.  If no argument is passed, clone this bit
     * set and {@link #notInPlace}.
     * @param {org.antlr.runtime.BitSet} [set]
     * @returns {org.antlr.runtime.BitSet}
     */
    complement: function(set) {
        if (set) {
            return set.subtract(this);
        } else {
            var s = this.clone();
            s.notInPlace();
            return s;
        }
    },

    /**
     * If no arguments are passed sets all bits to the complement of their
     * current values.  If one argument is passed sets each bit from the
     * beginning of the bit set to index1 (inclusive) to the complement of its
     * current value.  If two arguments are passed sets each bit from the
     * specified index1 (inclusive) to the sepcified index2 (inclusive) to the
     * complement of its current value.
     * @param {Number} index1
     * @param {Number} index2
     */
    notInPlace: function() {
        var minBit, maxBit, i, n;
        if (arguments.length===0) {
            for (i = this.bits.length - 1; i >= 0; i--) {
                this.bits[i] = ~this.bits[i];
            }
        } else {
            if (arguments.length===1) {
                minBit = 0;
                maxBit = arguments[0];
            } else {
                minBit = arguments[0];
                maxBit = arguments[1];
            }
            // make sure that we have room for maxBit
            this.growToInclude(maxBit);
            for (i = minBit; i <= maxBit; i++) {
                n = org.antlr.runtime.BitSet.wordNumber(i);
                this.bits[n] ^= org.antlr.runtime.BitSet.bitMask(i);
            }
        }

    },

    /**
     * Performs a logical OR of this bit set with the bit set argument.
     * If no argument is passed, return this bit set.  Otherwise a clone of
     * this bit set is modified so that a bit in it has the value true if and
     * only if it either already had the value true or the corresponding bit
     * in the bit set argument has the value true.
     * @param {org.antlr.runtime.BitSet} [a] a bit set.
     * @returns {org.antlr.runtime.BitSet}
     */
    or: function(a) {
		if ( !a ) {
			return this;
		}
        var s = this.clone();
        s.orInPlace(a);
        return s;
    },

    /**
     * Performs a logical {@link #or} in place.
     * @param {org.antlr.runtime.BitSet} [a]
     * @returns {org.antlr.runtime.BitSet}
     */
    orInPlace: function(a) {
		if ( !a ) {
			return;
		}
        // If this is smaller than a, grow this first
        if (a.bits.length > this.bits.length) {
            this.setSize(a.bits.length);
        }
        var min = Math.min(this.bits.length, a.bits.length),
            i;
        for (i = min - 1; i >= 0; i--) {
            this.bits[i] |= a.bits[i];
        }
    },

    /**
     * Sets the bit specified by the index to false.
     * @param {Number} bitIndex the index of the bit to be cleared.
     */
    remove: function(el) {
        var n = org.antlr.runtime.BitSet.wordNumber(el);
        if (n >= this.bits.length) {
            this.growToInclude(el);
        }
        this.bits[n] &= ~org.antlr.runtime.BitSet.bitMask(el);
    },

    /**
     * Grows the internal bits array to include at least nwords numbers.
     * @param {Number} nwords how many words the new set should be
     * @private
     */
    setSize: function(nwords) {
        var n = nwords - this.bits.length;
        while (n>=0) {
            this.bits.push(0);
            n--;
        }
    },

    /**
     * Returns the number of bits capable of being represented by this bit set
     * given its current size.
     * @returns {Number} the maximum number of bits that can be represented at
     *                   the moment.
     * @private
     */
    numBits: function() {
        return this.bits.length << org.antlr.runtime.BitSet.LOG_BITS; // num words * bits per word
    },

    /**
     * Return how much space is being used by the bits array not
     * how many actually have member bits on.
     * @returns {Number} the length of the internal bits array.
     * @private
     */
    lengthInLongWords: function() {
        return this.bits.length;
    },

    /**
     * Is this bit set contained within a?
     * @param {org.antlr.runtime.BitSet} a bit set
     * @returns {Boolean} true if and only if a is a subset of this bit set.
     */
    subset: function(a) {
        if (!a) { return false; }
        return this.and(a).equals(this);
    },

    /**
     * Subtract the elements of the argument bit set from this bit set in place.
     * That is, for each set bit in the argument bit set, set the corresponding
     * bit in this bit set to false.
     * @param {org.antlr.runtime.BitSet} a bit set.
     */
    subtractInPlace: function(a) {
        if (!a) { return; }
        // for all words of 'a', turn off corresponding bits of 'this'
        var i;
        for (i = 0; i < this.bits.length && i < a.bits.length; i++) {
            this.bits[i] &= ~a.bits[i];
        }
    },

    /**
     * Perform a {@link #subtractInPlace} on a clone of this bit set.
     * @param {org.antlr.runtime.BitSet} a bit set.
     * @returns {org.antlr.runtime.BitSet} the new bit set.
     */
    subtract: function(a) {
        if (!a || !(a instanceof org.antlr.runtime.BitSet)) { return null; }

        var s = this.clone();
        s.subtractInPlace(a);
        return s;
    },

    /* antlr-java needs this to make its class hierarchy happy . . .
    toList: function() {
		throw new Error("BitSet.toList() unimplemented");
	},
    */

    /**
     * Creates an array of the indexes of each bit set in this bit set.
     * @returns {Array}
     */
    toArray: function() {
        var elems = [], //new Array(this.size()),
            i,
            en = 0;
        for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) {
            if (this.member(i)) {
                elems[en++] = i;
            }
        }
        return elems;
    },

    /**
     * Returns the internal representation of this bit set.
     * This representation is an array of numbers, each representing 32 bits.
     * @returns {Array}
     */
    toPackedArray: function() {
        return this.bits;
    },

    /**
     * Returns a string representation of this bit set.
     * <p>For every index for which this BitSet contains a bit in the set state,
     * the decimal representation of that index is included in the result.
     * Such indices are listed in order from lowest to highest, separated by
     * ", " (a comma and a space) and surrounded by braces, resulting in the
     * usual mathematical notation for a set of integers.</p>
     * 
     * <p>If a grammar g is passed, print g.getTokenDisplayName(i) for each set
     * index instead of the numerical index.</p>
     *
     * <>If two arguments are passed, the first will be used as a custom
     * separator string.  The second argument is an array whose i-th element
     * will be added if the corresponding bit is set.</p>
     *
     * @param {Object|String} [arg1] an Object with function property
     *      getTokenDispalyName or a String that will be used as a list
     *      separator.
     * @param {Array} [vocabulary] array from which the i-th value will be
     *      drawn if the corresponding bit is set.  Must pass a string as the
     *      first argument if using this option.
     * @return A commma-separated list of values
     */
    toString: function() {
        if (arguments.length===0) {
            return this.toString1(null);
        } else {
            if (org.antlr.lang.isString(arguments[0])) {
                if (!org.antlr.lang.isValue(arguments[1])) {
                    return this.toString1(null);
                } else {
                    return this.toString2(arguments[0], arguments[1]);
                }
            } else {
                return this.toString1(arguments[0]);
            }
        }
    },

    /**
     * Transform a bit set into a string by formatting each element as an
     * integer separator The string to put in between elements
     * @private
     * @return A commma-separated list of values
     */
    toString1: function(g) {
        var buf = "{",
            separator = ",",
            i,
		    havePrintedAnElement = false;

        for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) {
            if (this.member(i)) {
                if (i > 0 && havePrintedAnElement ) {
                    buf += separator;
                }
                if ( g ) {
                    buf += g.getTokenDisplayName(i);
                }
                else {
                    buf += i.toString();
                }
				havePrintedAnElement = true;
            }
        }
        return buf + "}";
    },

    /**
     * Create a string representation where instead of integer elements, the
     * ith element of vocabulary is displayed instead.  Vocabulary is a Vector
     * of Strings.
     * separator The string to put in between elements
     * @private
     * @return A commma-separated list of character constants.
     */
    toString2: function(separator, vocabulary) {
        var str = "",
            i;
        for (i = 0; i < (this.bits.length << org.antlr.runtime.BitSet.LOG_BITS); i++) {
            if (this.member(i)) {
                if (str.length > 0) {
                    str += separator;
                }
                if (i >= vocabulary.size()) {
                    str += "'" + i + "'";
                }
                else if (!org.antlr.lang.isValue(vocabulary.get(i))) {
                    str += "'" + i + "'";
                }
                else {
                    str += vocabulary.get(i);
                }
            }
        }
        return str;
    }
};
