/*
 * Written by Dawid Kurzyniec and released to the public domain, as explained
 * at http://creativecommons.org/licenses/publicdomain
 */

package edu.emory.mathcs.util.collections.ints;

/**
 * Set is a collection with no duplicate elements. Primitive sets have some
 * features not found in object sets. A primitive set is
 * associated with a <em>domain</em> with boundaries defined by {@link #min()}
 * and {@link #max()}. All numbers contained within this set must fit
 * between min and max, inclusive. Attempt to add a number from outside the
 * domain will have no effect.
 *
 * <p>
 * It is possible to obtain a complement view of a
 * primitive set, using {@link #complementSet()}. The complement view contains
 * all numbers between min and max, inclusive, which are not contained in
 * this set. (In other words, complement view never contains numbers from
 * outside of the domain of this set).
 *
 * <p>
 * Contrary to standard Java collections, intervals in this primitive collection
 * package are <em>inclusive</em> on both sides. In other words, interval
 * [min, max] contains all numbers c such that min <= c <= max. (Otherwise,
 * MAX_VALUE could not be put in the set).
 *
 * @author Dawid Kurzyniec
 * @version 1.0
 */
public interface IntSet extends IntCollection {

    /**
     * The smallest number that can be stored in this set.
     * @return the smallest number that can be stored in this set
     */
    int min();

    /**
     * The largest number that can be stored in this set.
     * @return the largest number that can be stored in this set
     */
    int max();

    /**
     * Returns the number of elements in this set.
     * If exceeds Integer.MAX_VALUE, then Integer.MAX_VALUE is returned. 
     */
    int size();

    /**                                                   
     * Returns the number of elements in this set.        
     */                                                   
    int size64();                                        

    /**
     * Returns true if this set is empty; false otherwise.
     * @return true if this set is empty; false otherwise
     */
    boolean isEmpty();

    /**
     * Returns true if this set contains the specified number; false otherwise.
     * @return true if this set contains the specified number; false otherwise
     */
    boolean contains(int e);

    /**
     * Returns the iterator over numbers contained in this set.
     * @return the iterator over numbers contained in this set
     */
    IntIterator iterator();

    /**
     * Returns the newly allocated array containing all numbers from this
     * set, in the order returned by its iterator.
     * @return the array containing all numbers from this set
     */
    int[] toArray();

    /**
     * Returns an array containing all of the numbers in this set.
     * If the set fits in the specified array, it is returned therein.
     * Otherwise, a new array is allocated.
     *
     * <p>If this set makes any guarantees as to what order its elements
     * are returned by its iterator, this method must return the elements
     * in the same order.
     *
     * <p>Like the {@link #toArray()} method, this method acts as bridge between
     * array-based and collection-based APIs.  Further, this method may,
     * under certain circumstances, be used to save allocation costs.
     *
     * @param a the array into which the elements of this set are to be
     *        stored, if it is big enough; otherwise, a new array is allocated
     *        for this purpose.
     * @return an array containing all the elements in this set
     * @throws NullPointerException if the specified array is null
     */
    int[] toArray(int a[]);

    /**
     * Adds the specified number to this set if it is not already present
     * and if it falls within the domain.
     *
     * @param e number to be added to this collection
     * @return <tt>true</tt> if successfully added
     */
    boolean add(int e);

    /**
     * Removes the specified number from this set if it is present.
     *
     * @param e number to be removed from this collection
     * @return <tt>true</tt> if successfully removed
     */
    boolean remove(int e);

    /**
     * Returns <tt>true</tt> if this set contains all of the elements of the
     * specified collection.  If the specified collection is also a set, this
     * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
     *
     * @param  c collection to be checked for containment in this set
     * @return <tt>true</tt> if this set contains all of the elements of the
     * 	       specified collection
     * @throws NullPointerException if the specified collection is null
     * @see #contains(int)
     */
    boolean containsAll(IntCollection c);

    /**
     * Adds all of the elements in the specified collection to this set if
     * they're not already present, and if they fall within this set's domain.
     * If the specified collection is also a
     * set, the <tt>addAll</tt> operation effectively modifies this set so
     * that its value is the <i>union</i> of the two sets, intersected with
     * this set's domain.  The behavior of
     * this operation is undefined if the specified collection is modified
     * while the operation is in progress.
     *
     * @param  c collection containing elements to be added to this set
     * @return <tt>true</tt> if this set changed as a result of the call
     * @throws NullPointerException if the specified collection is null
     * @see #add(int)
     */
    boolean addAll(IntCollection c);

    /**
     * Retains only the elements in this set that are contained in the
     * specified collection.  In other words, removes from this set all of
     * its elements that are not contained in the specified collection.  If
     * the specified collection is also a set, this operation effectively
     * modifies this set so that its value is the <i>intersection</i> of the
     * two sets.
     *
     * @param  c collection containing elements to be retained in this set
     * @return <tt>true</tt> if this set changed as a result of the call
     * @see #remove(int)
     */
    boolean retainAll(IntCollection c);

    /**
     * Removes from this set all of its elements that are contained in the
     * specified collection.  If the specified collection is also a set,
     * this operation effectively modifies this set so that its value is the
     * <i>asymmetric set difference</i> of the two sets.
     *
     * @param  c collection containing elements to be removed from this set
     * @return <tt>true</tt> if this set changed as a result of the call
     * @see #remove(int)
     */
    boolean removeAll(IntCollection c);

    /**
     * Returns a complement view of this set. Complement view is a set that
     * has the same domain as this set, and consists of all numbers from the
     * domain that are not contained in this set. Changes done to this set
     * are reflected in the complement view after it is created.
     *
     * @return the complement view of this set
     */
    IntSet complementSet();

    /**
     * Removes all of the elements from this set.
     * The set will be empty after this call returns.
     */
    void clear();

    /**
     * Two sets are equal if they consists of the same elements.
     */
    boolean equals(Object o);

    /**
     *
     * @return int
     */
    int hashCode();

    /**
     * Returns true if this set contains all the numbers between
     * first and last, inclusive; false otherwise.
     * @return true if this set contains the specified interval; false otherwise
     */
    boolean containsInterval(int first, int last);

    /**
     * Adds to this set all the numbers between first and last, inclusive,
     * that are not already present in this set and beint to this set's domain.
     *
     * @param  first the beginning of the interval (inclusive)
     * @param  last the end of the interval (inclusive)
     * @return <tt>true</tt> if this set changed as a result of the call
     * @see #add(int)
     */
    boolean addInterval(int first, int last);

    /**
     * Retains in this set only the numbers between first and last, inclusive.
     * In other words, removes from this set all the numbers outside the
     * specified interval.
     *
     * @param  first the beginning of the interval (inclusive)
     * @param  last the end of the interval (inclusive)
     * @return <tt>true</tt> if this set changed as a result of the call
     * @see #retainAll()
     */
    boolean retainInterval(int first, int last);

    /**
     * Removes from this set all the numbers between first and last, inclusive.
     *
     * @param  first the beginning of the interval (inclusive)
     * @param  last the end of the interval (inclusive)
     * @return <tt>true</tt> if this set changed as a result of the call
     * @see #remove(int)
     * @see #removeAll()
     */
    boolean removeInterval(int first, int last);
}
