/* 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;


/**
 * A concrete EnumSet for enums with 64 or fewer elements.
 */
@SuppressWarnings("serial")
final class MiniEnumSet<E extends Enum<E>> extends EnumSet<E> {
    private static final int MAX_ELEMENTS = 64;

    private int size;

    private final E[] enums;

    private long bits;

    /**
     * Constructs an instance.
     *
     * @param elementType non-null; type of the elements
     * @param enums non-null; pre-populated array of constants in ordinal
     * order
     */
    MiniEnumSet(Class<E> elementType, E[] enums) {
        super(elementType);
        this.enums = enums;
    }

    private class MiniEnumSetIterator implements Iterator<E> {

        /**
         * The bits yet to be returned for bits. As values from the current index are returned,
         * their bits are zeroed out.
         */
        private long currentBits = bits;

        /**
         * The single bit of the next value to return.
         */
        private long mask = currentBits & -currentBits; // the lowest 1 bit in currentBits

        /**
         * The candidate for removal. If null, no value may be removed.
         */
        private E last;

        public boolean hasNext() {
            return mask != 0;
        }

        public E next() {
            if (mask == 0) {
                throw new NoSuchElementException();
            }

            int ordinal = Long.numberOfTrailingZeros(mask);
            last = enums[ordinal];

            currentBits &= ~mask;
            mask = currentBits & -currentBits; // the lowest 1 bit in currentBits

            return last;
        }

        public void remove() {
            if (last == null) {
                throw new IllegalStateException();
            }

            MiniEnumSet.this.remove(last);
            last = null;
        }
    }

    @Override
    public Iterator<E> iterator() {
        return new MiniEnumSetIterator();
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        bits = 0;
        size = 0;
    }

    @Override
    public boolean add(E element) {
        elementClass.cast(element); // Called to throw ClassCastException.
        long oldBits = bits;
        long newBits = oldBits | (1L << element.ordinal());
        if (oldBits != newBits) {
            bits = newBits;
            size++;
            return true;
        }
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends E> collection) {
        if (collection.isEmpty()) {
            return false;
        }
        if (collection instanceof EnumSet) {
            EnumSet<?> set = (EnumSet) collection; // raw type due to javac bug 6548436
            set.elementClass.asSubclass(elementClass); // Called to throw ClassCastException.

            MiniEnumSet<?> miniSet = (MiniEnumSet<?>) set;
            long oldBits = bits;
            long newBits = oldBits | miniSet.bits;
            bits = newBits;
            size = Long.bitCount(newBits);
            return (oldBits != newBits);
        }
        return super.addAll(collection);
    }

    @Override
    public boolean contains(Object object) {
        if (object == null || !isValidType(object.getClass())) {
            return false;
        }

        @SuppressWarnings("unchecked") // guarded by isValidType()
        Enum<E> element = (Enum<E>) object;
        int ordinal = element.ordinal();
        return (bits & (1L << ordinal)) != 0;
    }

    @Override
    public boolean containsAll(Collection<?> collection) {
        if (collection.isEmpty()) {
            return true;
        }
        if (collection instanceof MiniEnumSet) {
            MiniEnumSet<?> set = (MiniEnumSet<?>) collection;
            long setBits = set.bits;
            return isValidType(set.elementClass) && ((bits & setBits) == setBits);
        }
        return !(collection instanceof EnumSet) && super.containsAll(collection);
    }

    @Override
    public boolean removeAll(Collection<?> collection) {
        if (collection.isEmpty()) {
            return false;
        }
        if (collection instanceof EnumSet) {
            EnumSet<?> set = (EnumSet<?>) collection;
            if (!isValidType(set.elementClass)) {
                return false;
            }

            MiniEnumSet<E> miniSet = (MiniEnumSet<E>) set;
            long oldBits = bits;
            long newBits = oldBits & ~miniSet.bits;
            if (oldBits != newBits) {
                bits = newBits;
                size = Long.bitCount(newBits);
                return true;
            }
            return false;
        }
        return super.removeAll(collection);
    }

    @Override
    public boolean retainAll(Collection<?> collection) {
        if (collection instanceof EnumSet) {
            EnumSet<?> set = (EnumSet<?>) collection;
            if (!isValidType(set.elementClass)) {
                if (size > 0) {
                    clear();
                    return true;
                } else {
                    return false;
                }
            }

            MiniEnumSet<E> miniSet = (MiniEnumSet<E>) set;
            long oldBits = bits;
            long newBits = oldBits & miniSet.bits;
            if (oldBits != newBits) {
                bits = newBits;
                size = Long.bitCount(newBits);
                return true;
            }
            return false;
        }
        return super.retainAll(collection);
    }

    @Override
    public boolean remove(Object object) {
        if (object == null || !isValidType(object.getClass())) {
            return false;
        }

        @SuppressWarnings("unchecked") // guarded by isValidType()
        Enum<E> element = (Enum<E>) object;
        int ordinal = element.ordinal();
        long oldBits = bits;
        long newBits = oldBits & ~(1L << ordinal);
        if (oldBits != newBits) {
            bits = newBits;
            size--;
            return true;
        }
        return false;
    }

    @Override
    public boolean equals(Object object) {
        if (!(object instanceof EnumSet)) {
            return super.equals(object);
        }
        EnumSet<?> set =(EnumSet<?>) object;
        if (!isValidType(set.elementClass)) {
            return size == 0 && set.isEmpty();
        }
        return bits == ((MiniEnumSet<?>) set).bits;
    }

    @Override
    void complement() {
        if (enums.length != 0) {
            bits = ~bits;
            bits &= (-1L >>> (MAX_ELEMENTS - enums.length));
            size = enums.length - size;
        }
    }

    @Override
    void setRange(E start, E end) {
        int length = end.ordinal() - start.ordinal() + 1;
        long range = (-1L >>> (MAX_ELEMENTS - length)) << start.ordinal();
        bits |= range;
        size = Long.bitCount(bits);
    }
}
