/*
 * 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 org.apache.sis.util.collection;

import java.util.AbstractSet;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import org.opengis.util.CodeList;
import org.apache.sis.internal.util.CodeLists;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.NullArgumentException;
import org.apache.sis.internal.util.CheckedArrayList;


/**
 * A specialized {@code Set} implementation for use with {@link CodeList} values.
 * All elements in a {@code CodeListSet} are of the same {@code CodeList} class,
 * which must be final. Iterators traverse the elements in the order in which the
 * code list constants are declared.
 *
 * <h2>Implementation note</h2>
 * {@code CodeListSet} is implemented internally by bit vectors for compact and efficient storage.
 * All bulk operations ({@code addAll}, {@code removeAll}, {@code containsAll}) are very quick if
 * their argument is also a {@code CodeListSet} instance.
 *
 * <h2>Usage example</h2>
 * The following example creates a set of {@link org.opengis.referencing.cs.AxisDirection}s
 * for a (<var>x</var>,<var>y</var>,<var>z</var>) coordinate system:
 *
 * {@preformat java
 *   CodeListSet<AxisDirection> codes = new CodeListSet<>(AxisDirection.class);
 *   Collections.addAll(codes, AxisDirection.EAST, AxisDirection.NORTH, AxisDirection.UP),
 * }
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.4
 *
 * @param <E>  the type of code list elements in the set.
 *
 * @see java.util.EnumSet
 *
 * @since 0.3
 * @module
 */
public class CodeListSet<E extends CodeList<E>> extends AbstractSet<E>
        implements CheckedContainer<E>, Cloneable, Serializable
{
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = -6328082298556260980L;

    /**
     * A pool of code list arrays. When many {@code CodeListSet} instances are for the
     * same code list type, this allows those instances to share the same arrays.
     */
    @SuppressWarnings("rawtypes")
    private static final WeakHashSet<CodeList[]> POOL = new WeakHashSet<>(CodeList[].class);

    /**
     * The type of code list elements.
     *
     * @see #getElementType()
     */
    private final Class<E> elementType;

    /**
     * A bitmask of code list values present in this map.
     */
    private long values;

    /**
     * The bit set for supplementary values beyond the {@code values} mask, or {@code null}
     * if none. This is very rarely needed, but we need this field in case a code list has
     * more than 64 elements.
     *
     * <div class="note"><b>Implementation note:</b>
     * The standard {@link java.util.EnumSet} class uses different implementations depending on whether
     * the enumeration contains more or less than 64 elements. We can not apply the same strategy for
     * {@code CodeListSet}, because new code list elements can be created at runtime. Consequently this
     * implementation needs to be able to growth its capacity.</div>
     */
    private BitSet supplementary;

    /**
     * All possible code list elements, fetched when first needed.
     * Note that this array may need to be fetched more than once,
     * because code list elements can be dynamically added.
     *
     * @see #valueOf(int)
     */
    private transient E[] codes;

    /**
     * Creates an initially empty set for code lists of the given type.
     * The given {@code CodeList} type shall be final.
     *
     * @param  elementType  the type of code list elements to be included in this set.
     * @throws IllegalArgumentException if the given class is not final.
     */
    public CodeListSet(final Class<E> elementType) throws IllegalArgumentException {
        if (!Modifier.isFinal(elementType.getModifiers())) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.ClassNotFinal_1, elementType));
        }
        this.elementType = elementType;
    }

    /**
     * Creates set for code lists of the given type. If the {@code fill} argument is {@code false},
     * then the new set will be initially empty. Otherwise the new set will be filled with all code
     * list elements of the given type that are known at construction time. Note that if new code
     * list elements are created after the invocation of this {@code CodeListSet} constructor, then
     * those new elements will <em>not</em> be in this set.
     *
     * @param  elementType  the type of code list elements to be included in this set.
     * @param  fill {@code true} for filling the set with all known elements of the given type,
     *         or {@code false} for leaving the set empty.
     * @throws IllegalArgumentException if the given class is not final.
     */
    public CodeListSet(final Class<E> elementType, final boolean fill) throws IllegalArgumentException {
        this(elementType);
        if (fill) {
            codes = POOL.unique(CodeLists.values(elementType));
            int n = codes.length;
            if (n < Long.SIZE) {
                values = (1L << n) - 1;
            } else {
                values = -1;
                if ((n -= Long.SIZE) != 0) {
                    supplementary = new BitSet(n);
                    supplementary.set(0, n);
                }
            }
        }
    }

    /**
     * Returns the type of code list elements in this set.
     *
     * @return the type of code list elements in this set.
     */
    @Override
    public Class<E> getElementType() {
        return elementType;
    }

    /**
     * Returns the code list for the given ordinal value. This methods depends
     * only on the code list type; it does not depend on the content of this set.
     */
    final E valueOf(final int ordinal) {
        E[] array = codes;
        if (array == null || ordinal >= array.length) {
            codes = array = POOL.unique(CodeLists.values(elementType));
        }
        return array[ordinal];
    }

    /**
     * Removes all elements from this set.
     */
    @Override
    public void clear() {
        values = 0;
        final BitSet s = supplementary;
        if (s != null) {
            s.clear();
        }
    }

    /**
     * Returns {@code true} if this set does not contains any element.
     *
     * @return {@code true} if this set is empty.
     */
    @Override
    public boolean isEmpty() {
        final BitSet s;
        return values == 0 && ((s = supplementary) == null || s.isEmpty());
    }

    /**
     * Returns the number of elements in this set.
     *
     * @return the number of elements in this set.
     */
    @Override
    public int size() {
        int n = Long.bitCount(values);
        final BitSet s = supplementary;
        if (s != null) {
            n += s.cardinality();
        }
        return n;
    }

    /**
     * Adds the specified code list element in this set.
     *
     * @param  element  the code list element to add in this set.
     * @return {@code true} if this set has been modified as a consequence of this method call.
     */
    @Override
    public boolean add(final E element) {
        if (element == null) {
            final String message = CheckedArrayList.illegalElement(this, element, elementType);
            if (message == null) {
                /*
                 * If a unmarshalling process is under way, silently discard null element.
                 * This case happen when a codeListValue attribute in a XML file is empty.
                 * See https://issues.apache.org/jira/browse/SIS-157
                 */
                return false;
            }
            throw new NullArgumentException(message);
        }
        int ordinal = element.ordinal();
        if (ordinal < Long.SIZE) {
            return values != (values |= (1L << ordinal));
        }
        /*
         * The above code is sufficient in the vast majority of cases. In the rare cases where
         * there is more than 64 elements, create a BitSet for storing the supplementary values.
         */
        BitSet s = supplementary;
        if (s == null) {
            supplementary = s = new BitSet();
        }
        if (s.get(ordinal -= Long.SIZE)) {
            return false;
        }
        s.set(ordinal);
        return true;
    }

    /**
     * Removes the specified code list element from this set.
     * This methods does nothing if the given argument is {@code null} or is
     * not an instance of the code list class specified at construction time.
     *
     * @param  object  the code list element to remove from this set.
     * @return {@code true} if this set has been modified as a consequence of this method call.
     */
    @Override
    public boolean remove(final Object object) {
        if (elementType.isInstance(object)) {
            return clear(((CodeList<?>) object).ordinal());
        }
        return false;
    }

    /**
     * Clears the bit at the given ordinal value. This method is invoked by
     * {@link #remove(Object)} or by {@link Iter#remove()}.
     */
    final boolean clear(int ordinal) {
        if (ordinal < Long.SIZE) {
            return values != (values &= ~(1L << ordinal));
        }
        // Rare cases where there is more than 64 elements.
        final BitSet s = supplementary;
        if (s != null && s.get(ordinal -= Long.SIZE)) {
            s.clear(ordinal);
            return true;
        }
        return false;
    }

    /**
     * Returns {@code true} if this set contains the given element.
     * This methods returns {@code false} if the given argument is {@code null} or
     * is not an instance of the code list class specified at construction time.
     *
     * @param  object  the element to test for presence in this set.
     * @return {@code true} if the given object is contained in this set.
     */
    @Override
    public boolean contains(final Object object) {
        if (elementType.isInstance(object)) {
            int ordinal = ((CodeList<?>) object).ordinal();
            if (ordinal < Long.SIZE) {
                return (values & (1L << ordinal)) != 0;
            }
            // Rare cases where there is more than 64 elements.
            final BitSet s = supplementary;
            if (s != null) {
                return s.get(ordinal - Long.SIZE);
            }
        }
        return false;
    }

    /**
     * Returns {@code true} if this set contains all the elements of the given collection.
     *
     * @param  c  the collection to be checked for containment in this set.
     * @return {@code true} if this set contains all elements of the given collection.
     */
    @Override
    public boolean containsAll(final Collection<?> c) {
        if (c instanceof CodeListSet) {
            final CodeListSet<?> o = (CodeListSet<?>) c;
            if (elementType == o.elementType) {
                if (values == (values | o.values)) {
                    /*
                     * Code below this point checks for the rare cases
                     * where there is more than 64 code list elements.
                     */
                    final BitSet s = supplementary;
                    final BitSet os = o.supplementary;
                    if (( s == null ||  s.isEmpty()) &&
                        (os == null || os.isEmpty()))
                    {
                        return true;
                    }
                    if (s != null && os != null) {
                        final BitSet tmp = (BitSet) os.clone();
                        tmp.andNot(s);
                        return tmp.isEmpty();
                    }
                }
            }
            return false;
        }
        return super.containsAll(c);
    }

    /**
     * Adds all elements of the given collection to this set.
     *
     * @param  c  the collection containing elements to be added to this set.
     * @return {@code true} if this set changed as a result of this method call.
     */
    @Override
    public boolean addAll(final Collection<? extends E> c) throws IllegalArgumentException {
        if (c instanceof CodeListSet) {
            final CodeListSet<?> o = (CodeListSet<?>) c;
            /*
             * Following assertion should be ensured by parameterized types.
             */
            assert elementType.isAssignableFrom(o.elementType);
            boolean changed = (values != (values |= o.values));
            /*
             * Code below this point is for the rare cases
             * where there is more than 64 code list elements.
             */
            final BitSet os = o.supplementary;
            if (os != null) {
                final BitSet s = supplementary;
                if (s == null) {
                    if (!os.isEmpty()) {
                        supplementary = (BitSet) os.clone();
                        changed = true;
                    }
                } else if (changed) {
                    // Avoid the cost of computing cardinality.
                    s.or(os);
                } else {
                    final int cardinality = s.cardinality();
                    s.or(os);
                    changed = (cardinality != s.cardinality());
                }
            }
            return changed;
        }
        return super.addAll(c);
    }

    /**
     * Returns the bitmask to use for a bulk operation with an other set of code lists.
     */
    private long mask(final CodeListSet<?> other) {
        return (elementType == other.elementType) ? other.values : 0;
    }

    /**
     * Adds all elements of the given collection from this set.
     *
     * @param  c  the collection containing elements to be removed from this set.
     * @return {@code true} if this set changed as a result of this method call.
     */
    @Override
    public boolean removeAll(final Collection<?> c) {
        if (c instanceof CodeListSet) {
            boolean changed = (values != (values &= ~mask((CodeListSet<?>) c)));
            /*
             * Code below this point is for the rare cases
             * where there is more than 64 code list elements.
             */
            final BitSet s = supplementary;
            if (s != null) {
                final BitSet os = ((CodeListSet<?>) c).supplementary;
                if (os != null) {
                    if (changed) {
                        // Avoid the cost of computing cardinality.
                        s.andNot(os);
                    } else {
                        final int cardinality = s.cardinality();
                        s.andNot(os);
                        changed = (cardinality != s.cardinality());
                    }
                }
            }
            return changed;
        }
        return super.removeAll(c);
    }

    /**
     * Retains only the elements of the given collection in this set.
     *
     * @param  c  the collection containing elements to retain in this set.
     * @return {@code true} if this set changed as a result of this method call.
     */
    @Override
    public boolean retainAll(final Collection<?> c) {
        if (c instanceof CodeListSet) {
            boolean changed = (values != (values &= mask((CodeListSet<?>) c)));
            /*
             * Code below this point is for the rare cases
             * where there is more than 64 code list elements.
             */
            final BitSet s = supplementary;
            if (s != null) {
                final BitSet os = ((CodeListSet<?>) c).supplementary;
                if (os == null) {
                    changed |= !s.isEmpty();
                    s.clear();
                } else if (changed) {
                    // Avoid the cost of computing cardinality.
                    s.and(os);
                } else {
                    final int cardinality = s.cardinality();
                    s.and(os);
                    changed = (cardinality != s.cardinality());
                }
            }
            return changed;
        }
        return super.retainAll(c);
    }

    /**
     * Returns an iterator over the elements in this set.
     * The instance returned by this implementation will iterate over a snapshot of this
     * {@code CodeListSet} content at the time this method has been invoked. Changes in
     * this {@code CodeListSet} made after this method call will not affect the values
     * returned by the iterator.
     *
     * @return an iterator over the elements in this set.
     */
    @Override
    public Iterator<E> iterator() {
        return new Iter(values, supplementary);
    }

    /**
     * The iterator returned by {@link CodeListSet#iterator()}.
     */
    private final class Iter implements Iterator<E> {
        /**
         * Initialized to {@link CodeListSet#values}, then the bits are cleared as we
         * progress in the iteration. This value become 0 when the iteration is done.
         */
        private long remaining;

        /**
         * Initialized to a clone of {@link CodeListSet#supplementary}, then the bits are cleared
         * as we progress in the iteration. The bit set become empty when the iteration is done.
         */
        private final BitSet more;

        /**
         * Ordinal value of the last element returned by {@link #next()}, or -1 if none.
         */
        private int last;

        /**
         * Creates a new iterator initialized to the given values.
         */
        Iter(final long values, final BitSet supplementary) {
            remaining = values;
            more = (supplementary != null) ? (BitSet) supplementary.clone() : null;
            last = -1;
        }

        /**
         * Returns {@code true} if there is more elements to return.
         */
        @Override
        public boolean hasNext() {
            return remaining != 0 || (more != null && !more.isEmpty());
        }

        /**
         * Returns the next element.
         */
        @Override
        public E next() {
            int ordinal = Long.numberOfTrailingZeros(remaining);
            if (ordinal >= Long.SIZE) {
                // Rare case when we have more than 64 elements.
                if (more == null || (ordinal = more.nextSetBit(0)) < 0) {
                    throw new NoSuchElementException();
                }
                more.clear(ordinal);
                ordinal += Long.SIZE;
            }
            last = ordinal;
            remaining &= ~(1L << ordinal);
            return valueOf(ordinal);
        }

        /**
         * Removes the last element returned by this iterator.
         */
        @Override
        public void remove() {
            if (last < 0) {
                throw new IllegalStateException();
            }
            clear(last);
            last = -1;
        }
    }

    /**
     * Returns a new set of the same class containing the same elements than this set.
     *
     * @return a clone of this set.
     */
    @Override
    @SuppressWarnings("unchecked")
    public CodeListSet<E> clone() {
        final CodeListSet<E> clone;
        try {
            clone = (CodeListSet<E>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);                // Should never happen, since we are cloneable.
        }
        final BitSet s = supplementary;
        if (s != null) {
            clone.supplementary = (BitSet) s.clone();
        }
        return clone;
    }
}
