package jif.util;

/**
 * Base implementation for Collection.
 */
public abstract class AbstractCollection[label L] implements Collection[L] {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractCollection() {
    }

    public abstract Iterator[L]{this} iterator();
    public abstract int{L} size();

    public final boolean{L} isEmpty() {
        return size() == 0;
    }


    public boolean{L;o} contains(JifObject[L] o) {
        return contains(L, o);
    }

    public boolean{L} add{L}(JifObject[L]{L} o):{L} throws (ClassCastException{L}, IllegalArgumentException{L})
    {
        return false;
    }

    public boolean{L} add{L}(String{L} o):{L} throws (ClassCastException{L}, IllegalArgumentException{L}) {
        return add(new JifString[L](o));
    }
    public boolean{L} remove{L}(String{L} o) {
        return remove(new JifString[L](o));        
    }
    public boolean{L;o} contains{L}(String{L} o) {
        return contains(new JifString[L](o));                
    }
    public boolean{L;*lbl;lbl;o} contains{*lbl}(label lbl, String{*lbl} o) {
        return contains(lbl, new JifString[lbl](o));                        
    }



    public boolean{L} remove{L}(JifObject[L]{L} o) {
        try {
            Iterator[L] e = iterator();
            if (e != null) {
                if (o == null) {
                    while (e.hasNext()) {
                        if (e.next() == null) {
                            e.remove();
                            return true;
                        }
                    }
                }
                else {
                    while (e.hasNext()) {
                        if (o.equals(e.next())) {
                            e.remove();
                            return true;
                        }
                    }
                }
            }
        }
        catch (IllegalStateException e) { /* cant happen */ }
        catch (NoSuchElementException e) { /* cant happen */ }
        return false;
    }

    public boolean{L;c} containsAll(Collection[L]{L} c):{c} 
    throws (NullPointerException{c}) {
        if (c == null) throw new NullPointerException();
        int size = c.size();
        int i = 0;
        boolean containsAll = true;
        while (i < size) {
            try {
                if(!contains(c.get(i))) {
                    containsAll = false;
                    break;
                }
            }
            catch (IndexOutOfBoundsException impossible) { }
        }
        return containsAll;
    }

    public boolean{L} addAll{L}(Collection[L]{L} c) 
    throws (ClassCastException{L}, IllegalArgumentException{L}) {
        boolean{this;L} modified = false;
        if (c != null) {
            Iterator[L]{this;L} e = c.iterator();
            while (e != null && e.hasNext()) {
                try {
                    if(add(e.next())) {
                        modified = true;
                    }
                }
                catch (NoSuchElementException impossible) { }
            }
        }
        return modified;
    }

    public boolean{L} removeAll{L}(Collection[L]{L} c) {
        boolean modified = false;
        if (c != null) {
            Iterator[L] e = iterator();
            while (e != null && e.hasNext()) {
                try {
                    if(c.contains(e.next())) {
                        e.remove();
                        modified = true;
                    }
                }
                catch (IllegalStateException impossible) { }
                catch (NoSuchElementException impossible) { }
            }
        }
        return modified;
    }

    public boolean{L} retainAll{L}(Collection[L]{L} c) {
      return retainAll(L, c);
    }
    
    public boolean{L} retainAll{L}(label lbl, Collection[lbl]{L} c) where lbl <= L {
        boolean modified = false;
        Iterator[L] e = iterator();
        while (e != null && e.hasNext()) {
            try {
                JifObject[L] o = e.next();
                if(c == null || !c.contains(L, o)) {
                    e.remove();
                    modified = true;
                }
            }
            catch (IllegalStateException impossible) { }
            catch (NoSuchElementException impossible) { }
        }
        return modified;
    }

    public void clear{L}() {
        Iterator[L] e = iterator();
        while (e != null && e.hasNext()) {
            try {
                e.next();
                e.remove();
            }
            catch (IllegalStateException impossible) { }
            catch (NoSuchElementException impossible) { }

        }
    }

    public JifObject[L]{L}[]{L} toArray{L}() {
        try {
            JifObject[L]{L}[] newArray = new JifObject[L][this.size()]; 
            Iterator[L] e = iterator();
            int index = 0;
            while (e != null && e.hasNext()) {
                try {
                    JifObject[L] o = e.next();
                    newArray[index] = o;
                }
                catch (NoSuchElementException impossible) { }
                catch (ArrayIndexOutOfBoundsException impossible) { }
                index++;
            }
            return newArray;
        }
        catch (NegativeArraySizeException impossible) { }
        return null;
    }
    public JifObject[L]{L}const[]{L} toConstArray{L}() {
        try {
            return toArray().clone();
        }
        catch (NullPointerException imposs) { }
        return null;
    }

    public String{L} toString() {
        String s = "[";
        int i = 0;

        while (i < size()) {
            try {
                JifObject[L] obj = get(i);                
                if (obj == this) {
                    s += "(this Collection)";
                }
                else {
                    s += (obj==null?"null":obj.toString());
                }
                if (++i < size()) s += ", ";
            }
            catch (IndexOutOfBoundsException e) {}
        }
        s = s + "]";
        return s;
    }

}
