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

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

/**
 * @author Dawid Kurzyniec
 * @version 1.0
 */
public abstract class AbstractLongCollection implements LongCollection {

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

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

    public abstract LongIterator iterator();

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

        return a;
    }

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

        return a;
    }

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

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

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

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

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

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

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

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

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

    public String toString() {
        LongIterator 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();
    }
}
