package com.googlecode.totallylazy.collections;
import com.googlecode.totallylazy.functions.Function1;
import com.googlecode.totallylazy.functions.Function2;
import com.googlecode.totallylazy.functions.Functions;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.Pair;
import com.googlecode.totallylazy.predicates.Predicate;
import com.googlecode.totallylazy.predicates.Predicates;
import com.googlecode.totallylazy.Segment;
import com.googlecode.totallylazy.Unchecked;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import static com.googlecode.totallylazy.functions.Functions.call;
import static com.googlecode.totallylazy.Option.some;
import static com.googlecode.totallylazy.Unchecked.cast;
public abstract class AbstractTreeMap<K, V, Self extends TreeMap<K, V>> extends AbstractMap<K,V> implements TreeMap<K, V> {
protected final Comparator<K> comparator;
protected final K key;
protected final V value;
protected final Self left;
protected final Self right;
protected final TreeFactory factory;
protected final int size;
protected AbstractTreeMap(Comparator<K> comparator, K key, V value, Self left, Self right, TreeFactory factory) {
this.comparator = comparator;
this.key = key;
this.value = value;
this.left = left;
this.right = right;
this.factory = factory;
size = left.size() + right.size() + 1;
}
@Override
public TreeFactory factory() {
return factory;
}
@Override
public Comparator<K> comparator() {
return comparator;
}
@Override
public K key() {
return key;
}
@Override
public V value() {
return value;
}
@Override
public Self left() {
return left;
}
@Override
public Self left(TreeMap<K, V> newLeft) {
return cast(factory.create(comparator, key, value, newLeft, right()));
}
@Override
public Self right() {
return right;
}
@Override
public Self right(TreeMap<K, V> newRight) {
return cast(factory.create(comparator, key, value, left(), newRight));
}
@Override
public Self rotateLeft() {
TreeMap<K, V> b = right.left();
Self three = right(b);
return cast(right.left(three));
}
@Override
public Self rotateRight() {
TreeMap<K, V> c = left().right();
Self five = left(c);
return cast(left().right(five));
}
@Override
public PersistentList<Pair<K, V>> toPersistentList() {
return joinTo(PersistentList.constructors.<Pair<K, V>>empty());
}
@Override
public Option<V> lookup(K other) {
int difference = difference(other);
if (difference == 0) return Option.option(value);
if (difference < 0) return left.lookup(other);
return right.lookup(other);
}
@Override
public Self insert(K key, V value) {
int difference = difference(key);
if (difference == 0) return create(comparator, key, value, left, right);
if (difference < 0) return create(comparator, this.key, this.value, left.insert(key, value), right);
return create(comparator, this.key, this.value, left, right.insert(key, value));
}
@Override
public <S> S fold(S seed, Function2<? super S, ? super Pair<K, V>, ? extends S> callable) {
return right.fold(left.fold(Functions.call(callable, seed, pair()), callable), callable);
}
@Override
public Self delete(K key) {
int difference = difference(key);
if (difference == 0) {
if (left.isEmpty()) return right;
if (right.isEmpty()) return left;
Pair<? extends TreeMap<K, V>, Pair<K, V>> pair = left.removeLast();
TreeMap<K, V> newLeft = pair.first();
Pair<K, V> newRoot = pair.second();
return create(comparator, newRoot.first(), newRoot.second(), newLeft, right);
}
if (difference < 0) return create(comparator, this.key, value, left.delete(key), right);
return create(comparator, this.key, value, left, right.delete(key));
}
@Override
public Pair<K, V> first() throws NoSuchElementException {
if (left.isEmpty()) return pair();
return left.first();
}
@Override
public Pair<K, V> last() throws NoSuchElementException {
if (right.isEmpty()) return pair();
return right.last();
}
@Override
public Pair<Self, Pair<K, V>> removeFirst() {
if (left.isEmpty()) return Pair.pair(right, pair());
final Pair<? extends TreeMap<K, V>, Pair<K, V>> newLeft = left.removeFirst();
return Pair.pair(create(comparator, key, value, newLeft.first(), right), newLeft.second());
}
@Override
public Pair<Self, Pair<K, V>> removeLast() {
if (right.isEmpty()) return Pair.pair(left, pair());
final Pair<? extends TreeMap<K, V>, Pair<K, V>> newRight = right.removeLast();
return Pair.pair(create(comparator, key, value, left, newRight.first()), newRight.second());
}
@Override
public <C extends Segment<Pair<K, V>>> C joinTo(C rest) {
return cast(left.joinTo(right.joinTo(rest).cons(pair())));
}
@Override
public Self cons(Pair<K, V> newValue) {
return insert(newValue.first(), newValue.second());
}
@Override
public boolean contains(Object other) {
int difference = difference(Unchecked.<K>cast(other));
if (difference == 0) return true;
if (difference < 0) return left.contains(other);
return right.contains(other);
}
@Override
public boolean exists(Predicate<? super K> predicate) {
return predicate.matches(key) || left.exists(predicate) || right.exists(predicate);
}
@Override
public int hashCode() {
return 19 * value.hashCode() * left.hashCode() * right.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof AbstractTreeMap && value.equals(((AbstractTreeMap) obj).value) && left.equals(((AbstractTreeMap) obj).left) && right.equals(((AbstractTreeMap) obj).right);
}
@Override
public String toString() {
return String.format("(%s %s=%s %s)", left, key, value, right);
}
@Override
public Self empty() {
return self(factory.<K,V>create(comparator));
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Pair<K, V> head() throws NoSuchElementException {
return pair();
}
@Override
public Option<Pair<K, V>> headOption() {
return some(head());
}
@Override
public Self tail() throws NoSuchElementException {
return left.joinTo(right);
}
@Override
public Iterator<Pair<K, V>> iterator() {
return new TreeIterator<K, V>(this);
}
@Override
public int size() {
return size;
}
@Override
public Pair<K, V> get(int i) {
if (left.size() == i) return pair();
if (i < left.size()) return left.get(i);
return right.get(i - left.size() - 1);
}
@Override
public int indexOf(Object pair) {
int difference = difference(Unchecked.<Pair<K,V>>cast(pair).first());
if (difference == 0) return left.size();
if (difference < 0) return left.indexOf(pair);
return 1 + left.size() + right.indexOf(pair);
}
protected Pair<K, V> pair() {
return Pair.pair(key, value);
}
protected int difference(K key) {
return comparator.compare(key, this.key);
}
protected Self self(TreeMap<K, V> treeMap) {
return cast(treeMap);
}
protected Self create(Comparator<K> comparator, K key, V value, TreeMap<K, V> left, TreeMap<K, V> right) {
return self(factory.create(comparator, key, value, left, right));
}
}