if (jQuery) (function($) {
	function InstallTree(o, state, tree, item) {
		//alert('(' + item[0] + ')li.length=' + li.length);
		item.children('li').each(function() {
			if (jQuery.data(this, 'jquery.wstree:installed')) return;
			jQuery.data(this, 'jquery.wstree:installed', true);
			var node = jQuery(this);
			//alert('li(' + node.attr('href') + ')' + toggle.length + ',' + name.length);
			function closeNode() {
				node.children(o.actionToggle).removeClass(o.classActionOpened).addClass(o.classActionClosed);
				node.removeClass(o.classOpened).addClass(o.classClosed);
				o.setStatus(state, tree, node, false);
				o.hide(tree, o.getTree(tree, node), function(item) {
					o.removeTree(tree, item);
				});
			}
			function openNode() {
				node.children(o.actionToggle).removeClass(o.classActionClosed).addClass(o.classActionOpened);
				node.removeClass(o.classClosed).addClass(o.classOpened);
				o.rpc(tree, node, function(item) {
					o.show(tree, o.addTree(tree, node, item), function(item) {
						InstallTree(o, state, tree, item);
					});
				});
				o.setStatus(state, tree, node, true);
			}
			function toggleNode() {
				if (o.getStatus(state, tree, node)) {
					closeNode();
				} else {
					openNode();
				}
			}
			node.bind(o.eventNodeOpen, function() {
				//alert('eventNodeOpen');
				//if (o.getStatus(state, tree, node)) return;
				tree.trigger(o.eventNodeOpen, [node]);
				openNode();
				return false;
			});
			node.bind(o.eventNodeToggle, function() {
				//alert('eventNodeToggle');
				tree.trigger(o.eventNodeToggle, [node]);
				toggleNode();
				return false;
			});
			node.bind(o.eventNodeClose, function() {
				//alert('eventNodeClose');
				tree.trigger(o.eventNodeClose, [node]);
				closeNode();
				return false;
			});
			node.bind(o.eventNodeSelect, function() {
				//alert('eventNodeSelect');
				if (!o.getStatus(state, tree, node)) openNode();
				tree.trigger(o.eventNodeSelect, [node]);
				return false;
			});
			node.children(o.actionSelect).click(function() { node.trigger(o.eventNodeSelect); return false; });
			node.children(o.actionOpen).click(function() { node.trigger(o.eventNodeOpen); return false; });
			node.children(o.actionToggle).click(function() { node.trigger(o.eventNodeToggle); return false; });
			if (o.getStatus(state, tree, node)) {
				node.trigger(o.eventNodeOpen);
			} else {
				node.trigger(o.eventNodeClose);
			}
		});
	}
	jQuery.fn.extend({
		wstree: function(o) {
			o = jQuery.extend({
				eventNodeOpen:		'Tree:Node:Open',
				eventNodeToggle:	'Tree:Node:Toggle',
				eventNodeClose:		'Tree:Node:Close',
				eventNodeSelect:	'Tree:Node:Select',

				classOpened:		'TreeNodeOpened',
				classClosed:		'TreeNodeClosed',

				actionToggle:		'.TreeActionToggle',
				actionSelect:		'.TreeActionSelect',
				actionOpen:		'.TreeActionOpen',
				classIcon:		'.TreeNodeIcon',

				classActionOpened:	'TreeActionOpened',
				classActionClosed:	'TreeActionClosed',

				show:			function(tree, node, callback) {
					if (false && !node.is(":hidden")) {
						callback(node);
						return;
					}
					node.slideDown();//, function() {
					//	callback(node);
					//});
					callback(node);
				},
				hide:			function(tree, node, callback) {
					if (node.is(":hidden")) {
						callback(node);
						return;
					}
					node.slideUp(function() {
						callback(node);
					});
				},

				addTree:		function(tree, node, item) {
					var ptr = node.children('ul');
					if (item != null) {
						ptr.remove();
						ptr = node.append(item).children('ul').hide();
					}
					return ptr;
				},
				removeTree:		function(tree, item) {
					item.remove();
				},
				getTree:		function(tree, node) {
					return node.children('ul');
				},
							
				rpc:			function(tree, node, callback) {
					callback();
				},

				getStatus:		function(state, tree, node) {
					return state[node.attr('href')];
				},
				setStatus:		function(state, tree, node, value) {
					if (value) {
						state[node.attr('href')] = true;
					} else {
						delete state[node.attr('href')];
					}
				}
			}, o);
			this.each(function() {
				var tree = jQuery(this);
				var state = o.state ? o.state : {};
				try {
					InstallTree(o, state, tree, tree);
					o.show(tree, tree, function(item) { });
				} catch (e) {
					//alert(e);
				}
				//alert('tree install done');
			});
			return this;
		}
	});
})(jQuery);

