package com.googlecode.totallylazy.collections;
import com.googlecode.totallylazy.functions.Function1;
import com.googlecode.totallylazy.functions.Function2;
import com.googlecode.totallylazy.functions.Callables;
import com.googlecode.totallylazy.functions.Curried2;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.Pair;
import com.googlecode.totallylazy.predicates.Predicate;
import com.googlecode.totallylazy.Segment;
import com.googlecode.totallylazy.Unchecked;
import com.googlecode.totallylazy.iterators.SegmentIterator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import static com.googlecode.totallylazy.Option.some;
import static com.googlecode.totallylazy.Unchecked.cast;
public class TreeSet<T> extends AbstractCollection<T> implements PersistentSortedSet<T> {
private final PersistentSortedMap<T, T> map;
private TreeSet(PersistentSortedMap<T, T> map) {
this.map = map;
}
public static <T> PersistentSortedSet<T> treeSet(PersistentSortedMap<T, T> map) {
return new TreeSet<T>(map);
}
private Pair<PersistentSortedSet<T>, T> treeSet(Pair<? extends PersistentSortedMap<T, T>, Pair<T, T>> pair) {
return Pair.pair(treeSet(pair.first()), pair.second().first());
}
@Override
public PersistentList<T> toPersistentList() {
return map.toSequence().map(Callables.<T>first()).toPersistentList();
}
@Override
public Option<T> lookup(T value) {
return map.lookup(value);
}
@Override
public PersistentSortedSet<T> delete(T value) {
return treeSet(map.delete(value));
}
@Override
public T first() throws NoSuchElementException {
return map.first().first();
}
@Override
public T last() throws NoSuchElementException {
return map.last().first();
}
@Override
public Pair<PersistentSortedSet<T>, T> removeFirst() {
return treeSet(map.removeFirst());
}
@Override
public Pair<PersistentSortedSet<T>, T> removeLast() {
return treeSet(map.removeLast());
}
@Override
public Set<T> toSet() {
return map.keys().toSet();
}
@Override
public T get(int i) {
return map.get(i).first();
}
@Override
public int indexOf(Object t) {
return map.indexOf(pair(t));
}
@Override
public PersistentSortedSet<T> empty() {
return treeSet(map.empty());
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public T head() throws NoSuchElementException {
return map.head().first();
}
@Override
public Option<T> headOption() {
return isEmpty()
? Option.<T>none()
: some(head());
}
@Override
public PersistentSortedSet<T> tail() throws NoSuchElementException {
return treeSet(map.tail());
}
@Override
public PersistentSortedSet<T> cons(T head) {
return treeSet(map.cons(pair(head)));
}
@Override
public <C extends Segment<T>> C joinTo(C rest) {
if (map.isEmpty()) return rest;
return cast(tail().joinTo(rest).cons(head()));
}
@Override
public boolean contains(Object other) {
return map.contains(other);
}
@Override
public boolean exists(Predicate<? super T> predicate) {
return map.exists(predicate);
}
@Override
public int size() {
return map.size();
}
@Override
public Iterator<T> iterator() {
return SegmentIterator.iterator(toPersistentList());
}
private Pair<T, T> pair(Object head) {
return Pair.pair(Unchecked.<T>cast(head), Unchecked.<T>cast(head));
}
@Override
public <S> S fold(S seed, final Function2<? super S, ? super T, ? extends S> callable) {
return map.fold(seed, new Curried2<S, Pair<?, T>, S>() {
@Override
public S call(S s, Pair<?, T> pair) throws Exception {
return callable.call(s, pair.second());
}
});
}
}