package fr.umlv.conc;

import java.util.Objects;
import java.util.StringJoiner;
import java.util.function.Consumer;

public class Tree<E extends Comparable<? super E>> {
  static class Node<E extends Comparable<? super E>> {
    private Node<E> left;
    private Node<E> right;
    private E value;
    private int size;
    
    boolean add(E element) {
      if (value == null) {
        value = element;
        size++;
        return true;
      }
      if (element.equals(value)) {
        return false;
      }
      size++;
      if (element.compareTo(value) < 0) {
        if (left == null) {
          left = new Node<>();
        }
        return left.add(element);
      }
      if (right == null) {
        right = new Node<>();
      }
      return right.add(element);
    }
    
    void forEach(Consumer<? super E> consumer) {
      if (left != null) {
        left.forEach(consumer);
      }
      if (value != null) {
        consumer.accept(value);
      }
      if (right != null) {
        right.forEach(consumer);
      }
    }
  }
  
  private final Node<E> root = new Node<>();
  
  public boolean add(E element) {
    Objects.requireNonNull(element);
    return root.add(element);
  }
  
  public void forEach(Consumer<? super E> consumer) {
    Objects.requireNonNull(consumer);
    root.forEach(consumer);
  }
  
  @Override
  public String toString() {
    var joiner = new StringJoiner(", ", "[", "]");
    forEach(element -> joiner.add(element.toString()));
    return joiner.toString();
  }
  
  public static void main(String[] args) {
    var tree = new Tree<String>();
    tree.add("hello");
    tree.add("ben");
    tree.add("bob");
    tree.add("alice");
    
    System.out.println(tree);
  }
}
