/**
 *
 *	Tree class
 *	Usage: 
 *	<div id="menu">
 *	<ul>
 *		<li>
 *			<a href="" class="folder">Folder</a>
 *			<ul>
 *				<li>Item 1</li>
 *				<li>Item 2</li>
 *			</ul>
 *		</li>
 *	</ul>
 *	</div>
 *	<script type="text/javascript">var tree = new W.Tree({container: 'menu', className: 'group'});</script>
 *
 *	@param {Object}	param 	Param object
 *
 *	@requires W
 *	@requires W.Event
 *	@requires W.Dom
 *	@requires W.Cookie
 *
 *	@constructor
 */
W.Tree = function(param)
{
	this.init(param);
};



W.Tree.prototype = {

	
	container	: null,			// container for tree
	triggers	: null,			// trigger nodes for opening/closing
	className	: 'folder',		// className for triggers
	state		: [],			// array of open folders
	folderClass	: '',			// className for "folder" nodes
	openRoot	: false,		// should the first folder be opened automatically?


	init : function(param)
	{
		if (!param.container) { return; }
		
		this.triggers		= [];
		this.state			= [];
		this.container		= W.$(param.container);
		this.className		= param.className || this.className;
		this.folderClass	= param.folderClass || this.folderClass;
		this.openRoot		= param.openRoot == undefined ? this.openRoot : param.openRoot;
		
		this.refresh();
		
		W.Event.add(this);
	},
	
	
	
	// find nested <ul> and add icon for opening/closing <ul>
	refresh : function()
	{
		if (this.folderClass) { this.all_folders(); } else { this.folders_with_content(); }
		if (this.openRoot) { this.open_root() }
	},
	
	
	
	folders_with_content : function()
	{
		var obj		= this;
		var lists	= this.container.getElementsByTagName('ul');
		var li, a;
		
		this.triggers	= [];
		
		
		for (var i = lists.length; --i >= 0; ) {
			a			= document.createElement('a');
			a.className	= this.className;
			a.onclick	= function(e) { obj.toggle(e); };
			//a.innerHTML = i;

			li	= lists[i].parentNode;
			if (this.restore(li)) {
				a.className += ' expanded';
				lists[i].style.display	= 'block';
			}
			
			if (li.tagName.toUpperCase() == 'LI') { 
				li.insertBefore(a, lists[i]); 
				this.triggers.push(a);
			}
		}
	},
	
	
		
	all_folders : function()
	{
		var obj		= this;
		var lis		= this.container.getElementsByTagName('li');
		var li, a, ul;
		var re		= new RegExp(this.folderClass);
		
		this.triggers	= [];
		
		for (var i = lis.length; --i >= 0; ) {
			li	= lis[i];
			
			if (li.className.match(re)) {
				a			= document.createElement('a');
				a.className	= this.className;
				a.onclick	= function(e) { obj.toggle(e); };
				
				ul			= li.getElementsByTagName('ul')[0] || null;

				if (this.restore(li)) {
					a.className += ' expanded';
					if (ul) { ul.style.display	= 'block'; }
				}

				li.insertBefore(a, ul); 
				this.triggers.push(a);
			}
		}
	},
	
	
	
	open_root : function()
	{
		var trigger	= this.triggers[this.triggers.length - 1];
		
		if (!trigger) { return; }
		
		W.Dom.addClassName(trigger, 'expanded');
		var ul	= trigger.parentNode.getElementsByTagName('ul')[0];
		if (ul) { ul.style.display = 'block'; }
	},
	
	
	
	toggle : function(e)
	{
		W.Event.stop(e);
		
		var link	= W.Event.getTarget(e);
		var li		= link.parentNode;
		var ul		= li.getElementsByTagName('ul')[0];
		
		if (ul) {
			var display	= W.Dom.getStyle(ul, 'display');
			
			if (display == 'block') {
				ul.style.display = 'none';
				W.Dom.removeClassName(link, 'expanded');
			} else { 
				ul.style.display = 'block';
				W.Dom.addClassName(link, 'expanded');
				
				// show <li> nodes that are hidden after a search
				var lis = ul.getElementsByTagName('li');
				for (var i = lis.length; --i >= 0; ) {
					if (lis[i].parentNode == ul) { lis[i].style.display = 'block'; }
				}
			}
		} else {
			// empty folder
			if (W.Dom.hasClassName(link, 'expanded')) {
				W.Dom.removeClassName(link, 'expanded');
			} else {
				W.Dom.addClassName(link, 'expanded');
			}
		}
	},
	
	
	
	close_all : function()
	{
		var triggers		= this.triggers;
		var ul;
		
		for (var i = triggers.length; --i >= 0; ) {
			//console.log(i + ', ' + triggers[i].innerHTML + ', ' + triggers[i].parentNode);
			ul	= triggers[i].parentNode.getElementsByTagName('ul')[0];
			ul.style.display	= 'none';
			W.Dom.removeClassName(triggers[i], 'expanded');
		}
	},
	
	
	
	open_all : function()
	{
		var triggers		= this.triggers;
		var ul;

		for (var i = triggers.length; --i >= 0; ) {
			ul	= triggers[i].parentNode.getElementsByTagName('ul')[0];
			ul.style.display	= 'block';
			W.Dom.addClassName(triggers[i], 'expanded');
		}
	},
	
	
	
	onFilter : function(e)
	{
		var tree	= e.source;
		
		if (tree.form.value === '') { this.close_all(); }
	},
	
	
	
	onFilterShow : function(e)
	{
		var node	= e.target;
		
		while (node = node.previousSibling) {
			if (node.className == this.className) { W.Dom.addClassName(node, 'expanded'); }
		}
	},
	
	
	
	preserve : function()
	{
		var li, triggers = this.triggers;
			
		this.state = [];
				
		for (var i = triggers.length; --i >= 0; ) {
			if (W.Dom.hasClassName(triggers[i], 'expanded')) {
				li	= triggers[i].parentNode;
				if (li) { 
					this.state.push(li.getAttribute('data-id')); 
					//console.log('added ' + li.getAttribute('data-id'));
				}
			}
		}
	},
	
	
	
	restore : function(node)
	{		
		if (!node) { return false; }
				
		for (var i = this.state.length; --i >= 0; ) {
			if (node.getAttribute('data-id') == this.state[i]) { return true; }
		}
		
		return false;
	}

};
