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

/**
 * @author Dawid Kurzyniec
 * @version 1.0
 */
public abstract class AbstractIntCollection implements IntCollection {

    public int size() {                                                         
        int size64 = size64();                                                 
        if (size64 > 0 && size64 <= Integer.MAX_VALUE) return (int)size64;      
        if (size64 == 0 && !contains((int)0)) return 0;                        
        return Integer.MAX_VALUE;                                               
    }                                                                           
                                                                                
    public int size64() {                                                      
        int size = 0;                                                          
        for (IntIterator itr = iterator(); itr.hasNext();) size++;             
        return size;                                                            
    }                                                                           
                                                                                
//    public int size() {                                                       // PREPROC: except Int,Int
//        int size = 0;                                                        // PREPROC: except Int,Int
//        for (IntIterator itr = iterator(); itr.hasNext();) size++;           // PREPROC: except Int,Int
//        return size;                                                          // PREPROC: except Int,Int
//    }                                                                         // PREPROC: except Int,Int
//                                                                              // PREPROC: except Int,Int
    public boolean isEmpty() {
        return size() == 0;
    }

    public boolean contains(int e) {
        for (IntIterator itr = iterator(); itr.hasNext();) {
            if (itr.next() == e) return true;
        }
        return false;
    }

    public abstract IntIterator iterator();

    public int[] toArray() {
        int[] a = new int[size()];
        int i=0;
        for (IntIterator itr = iterator(); itr.hasNext();) {
            a[i++] = itr.next();
        }

        return a;
    }

    public int[] toArray(int[] a) {
        int size = size();
        if (a.length < size) a = new int[size];
        int i=0;
        for (IntIterator itr = iterator(); itr.hasNext();) {
            a[i++] = itr.next();
        }

        return a;
    }

    public boolean add(int e) {
        throw new UnsupportedOperationException();
    }

    public boolean remove(int e) {
        for (IntIterator itr = iterator(); itr.hasNext();) {
            if (itr.next() == e) {
                itr.remove();
                return true;
            }
        }
        return false;
    }

    public boolean containsAll(IntCollection c) {
        for (IntIterator itr = c.iterator(); itr.hasNext();) {
            if (!contains(itr.next())) return false;
        }
        return true;
    }

    public boolean addAll(IntCollection c) {
        boolean modified = false;
        for (IntIterator itr = c.iterator(); itr.hasNext();) {
            modified |= add(itr.next());
        }
        return modified;
    }

    public boolean retainAll(IntCollection c) {
        boolean modified = false;
        for (IntIterator itr = iterator(); itr.hasNext();) {
            if (!c.contains(itr.next())) {
                itr.remove();
                modified = true;
            }
        }
        return modified;
    }

    public boolean removeAll(IntCollection c) {
        boolean modified = false;

        if (c == this) {
            modified = !isEmpty();
            clear();
            return modified;
        }

        for (IntIterator itr = iterator(); itr.hasNext();) {
            if (c.contains(itr.next())) {
                itr.remove();
                modified = true;
            }
        }
        return modified;
    }

    public void clear() {
        for (IntIterator itr = iterator(); itr.hasNext();) {
            itr.next();
            itr.remove();
        }
    }

    public String toString() {
        IntIterator itr = iterator();
        StringBuffer buf = new StringBuffer();
        buf.append('[');
        while (itr.hasNext()) {
            buf.append(itr.next());
            if (itr.hasNext()) buf.append(',');
        }
        buf.append(']');
        return buf.toString();
    }
}
