const { Node, Link, Graph } = require("./graph");

class TreeNode extends Node {
	constructor(id){
		super(id);
		this.depth = null; 
	}
}

class Tree extends Graph {
	constructor(NodeType,rootNode){
		super(NodeType);
		this.root = rootNode;
		this.root.depth = 0;
		this.levels = [new Set(this.root.id)];
		super.addNode(this.root);
	}

  	addLink(link) {
  		console.log("You cannot add Link because its deprecated ...Use Insert");
		return;
	}
	addNode(node){
		console.log("You cannot add Node because its deprecated ...Use Insert");
		return;
	}

	insert(node,parentNode){
		if(this.nodes[node.id]){
			throw new Error("Node already Exists")
		}
		if(!this.nodes[parentNode.id]){
			throw new Error("Parent Node does not Exist....Insert First ")
		}
		let parentLevel = parentNode.depth;
		node.depth = parentLevel + 1;
		if(this.levels.length <= node.depth){
			this.levels[node.depth] = new Set();
		}

		this.levels[node.depth].add(node.id);
		let link = new Link(parentNode,node);
		super.addNode(node);
		super.addLink(link);

	}
	print() {
		console.log("§§§§§§§  Tree Structure 	 §§§§§§§§§§");

		this.levels.forEach((level, index) => {
			console.log("Level ", index);
			level.forEach( id => console.log(` ${id} `));
		});
		console.log("§§§§§§§  Tree Structure End §§§§§§§§§§");
	}

	remove(node){
		this.cleanup(node)
		this.levels[node.depth].delete(node.id);
		if(this.levels[node.depth].size === 0)
			this.levels.length = node.depth;

		super.removeNode(node);
	}

	cleanup(parent){
		let children = this.getChildren(parent);
		// console.log(children);
		children.forEach(child => {
			// console.log(child);
			this.remove(child)
		});

	}

	getChildren(node){
		// console.log(node)
		return [...this.links[node.id].out].map(link => link.to);
	}

	getLevel(depth) {
		return this.levels[depth];
	}

}
var A = new TreeNode("A");
let tree = new Tree(TreeNode,A);



var B = new TreeNode('B');
var C = new TreeNode('C');
var D = new TreeNode('D');
var E = new TreeNode('E');
var F = new TreeNode("F");


tree.insert(B,A)
tree.insert(C,A)
tree.insert(D,B)
tree.insert(E,D)
tree.insert(F,D)

tree.print();

tree.remove(D)

tree.print();
