package binary_tree;

import java.util.List;

public class LinkedBinaryTree<E> implements BinaryTree<E>{
	
	// VARIABILI D'INSTANZA
	private BinaryNode<E> root;
	private int size;
	
	// Metodi costruttori
	public LinkedBinaryTree() {
		root = null;
		size = 0;
	}
	
	public LinkedBinaryTree(E data) {
		root = new BinaryNode<E>(data);
		size = 1;
	}
	
	public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
		root = new BinaryNode<E>(left.root, data, right.root);
		size = 1 + left.size + right.size;
	}
	
	// METODI
	
	public int size() {
		return size;
	}
	
	@Override
	public boolean isEmpty() {
		return root == null;
	}
	
	public E getRoot() {
		if (isEmpty()) return null;
		return root.getData();
	}
	
	public BinaryNode<E> getRootNode() {
		if (isEmpty()) return null;
		return root;
	}
	
	public void clear() {
		root = null;
		size = 0;
	}
	
	private int getSize(BinaryNode<E> node) {
		if (node == null) return 0;
		
		int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
		int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
		
		return 1 + nLeft + nRight;
	}
	
	public LinkedBinaryTree<E> removeLeft() {
		LinkedBinaryTree<E> leftTree = null;
		if (root.getLeft() == null) return leftTree;
		
		leftTree = new LinkedBinaryTree<E>();
		leftTree.root = root.getLeft();
		leftTree.size = getSize(root.getLeft());
		leftTree.root.setAsRoot();
		
		size = size - leftTree.size;
		
		return leftTree;
	}
	
	public LinkedBinaryTree<E> removeRight() {
		LinkedBinaryTree<E> rightTree = null;
		if (root.getRight() == null) return rightTree;
		
		rightTree = new LinkedBinaryTree<E>();
		rightTree.root = root.getRight();
		rightTree.size = getSize(root.getRight());
		rightTree.root.setAsRoot();
		
		size = size - rightTree.size;
		
		return rightTree;
	}
	
	protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
		if (root == null) return null;
		if (root.getData().equals(targetElement)) return root;
		BinaryNode<E> resNode;
		resNode = find(targetElement, root.getLeft());
		if (resNode == null) resNode = find(targetElement, root.getRight());
		return resNode;
	}
	
	public boolean remove(E targetElement) {
		if (targetElement == null) return false;
		BinaryNode<E> temp = find(targetElement, root);
		if (temp != null) {
			temp.setData(null);
			return true;
		} 
		return false;
	}
	
	public boolean contains(E targetElement) {
		return find(targetElement, root) != null;
	}
	
	// ITERATORE PREORDER
	
	/*
	 * Qui si utilizza il metodo del preorder.
	 * Le regole per il preorder sono queste:
	 * 		- Visita prima se stesso
	 * 		- Poi visita tutto ciò che si trova sinistra
	 * 		- Infine visita tutto ciò che si trova a destra
	 */
	
	protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
		if (node == null) return;
		
		
	}
	
}
