var WTDom = function() {
	var results = {};
	
	return {
		init: function() {
			// Usage: WTDom.wRecursiveTest(document.body, 4)  for traversing a complete binary tree of depth 4
			// Alternatively you can paste any html content inside <body><div id="start"></div></body>
			// and comment out the setUp function.
		},
		
		// cleans the DOM and create a complete binary tree of level n 
		setUp: function(level) {
			document.body.innerHTML = '';
			var rootN = document.createElement('div');
			rootN.className = 'start';
			document.body.appendChild(rootN);
			this.createTree(document.body.firstChild, level);
		},
		
		wRecursiveTest: function(node, level) {
			this.setUp(level);
			var recursiveProfile = this.setProfile();
			this.wRecursive(node, function(w) { w.className = 'testClass'; });
			var recursiveTime = this.stopProfile(recursiveProfile);
			
			console.log(recursiveTime);
		},
		
		wIterativeTest: function(node, level) {
			this.setUp(level);
			var iterativeProfile = this.setProfile();
			this.wIterative(node, function(w) { w.className = 'testClass'; });
			var iterativeTime = this.stopProfile(iterativeProfile);
			
			console.log(iterativeTime);
		},
				
		setProfile: function() {
			return new Date().getTime();
		},
		
		stopProfile: function(startTime) {
			return new Date().getTime() - startTime;
		},
		
		// from Crockford's “Theory of the DOM”
		wRecursive: function(node, func) {
	        func(node); 
	        node = node.firstChild;
	 		while (node) { 
	            this.wRecursive(node, func); 
	        	node = node.nextSibling; 
			}
	    },
		
		// the iterative alternative
		wIterative: function(node, func) {
			var rootback = false;
			var rootnode = node;
			func(node);
			node = node.firstChild;
			while (!rootback) {
				func(node);
				if (node.firstChild != null) node = node.firstChild;
				else if (node.nextSibling != null) node = node.nextSibling;
				else {
					while (node.parentNode.nextSibling == null && node != rootnode && node.parentNode.firstChild != rootnode) {
						node = node.parentNode;
					}
					if (node.parentNode.nextSibling != null) node = node.parentNode.nextSibling;
					else rootback = true;
				}
			}
		},

		createTree: function(node, height, complete) {
			if (height > 0) {
				height -= 1;
				var child = document.createElement('div');
				var sibling = document.createElement('div');
				child.className = 'child';
				sibling.className = 'sibling';	
				node.appendChild(child);
				node.parentNode.appendChild(sibling);
				this.createTree(node.firstChild, height);
				this.createTree(node.nextSibling, height);
			}
		},
		
		// level-order traversing
		viewTree: function(root, func) {
		  	var node = '';
			var oldk = null;
			var k = 0;
			var c = 2;
			var q = [];
		  	q.push(root);
		  	while (q.length != 0) {
		    	node = q.splice(0,1)[0]; // first-in first-out
		    	func(node)
				k = Math.floor(Math.log(c) / Math.LN2); // assuming a perfect binary tree
				if (k != oldk) {
					oldk = k;
					console.log("Level "+oldk+":"+k+":"+c);
				}
				c += 1;
		    	if (node.firstChild != null) q.push(node.firstChild);
		    	if (node.nextSibling != null) q.push(node.nextSibling);
			}
		}
	}
}();