// jQuery File Tree Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 24 March 2008
//
// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
//
// Usage: $('.fileTreeDemo').fileTree( options, callback )
//
// Options:  root           - root folder to display; default = /
//           script         - location of the serverside AJAX file to use; default = jqueryFileTree.php
//           folderEvent    - event to trigger expand/collapse; default = click
//           expandSpeed    - default = 500 (ms); use -1 for no animation
//           collapseSpeed  - default = 500 (ms); use -1 for no animation
//           expandEasing   - easing function to use on expand (optional)
//           collapseEasing - easing function to use on collapse (optional)
//           multiFolder    - whether or not to limit the browser to one subfolder at a time
//           loadMessage    - Message to display while initial tree loads (can be HTML)
//
// History:
//
// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
// 1.00 - released (24 March 2008)
//
// TERMS OF USE
// 
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC. 
//
if (jQuery) (function($) {

	$.extend($.fn, {
		fileTree: function(o, handleLeafEvt, handleNodeEvt, onComplete) {
			// Defaults
			if (!o) var o = {};
			if (o.root == undefined) o.root = '/';
			if (o.script == undefined) o.script = '';
			if (o.folderEvent == undefined) o.folderEvent = 'click';
			if (o.expandSpeed == undefined) o.expandSpeed = 500;
			if (o.collapseSpeed == undefined) o.collapseSpeed = 500;
			if (o.expandEasing == undefined) o.expandEasing = null;
			if (o.collapseEasing == undefined) o.collapseEasing = null;
			if (o.multiFolder == undefined) o.multiFolder = true;
			if (o.loadMessage == undefined) o.loadMessage = _('Loading');
			if (o.loadEntireTree == undefined) o.loadEntireTree = false;
			if (o.nodeClass == undefined) o.nodeClass = 'directory';
			if (o.leafClass == undefined) o.leafClass = 'file';
			if (o.startExpanded == undefined) o.startExpanded = false;
			o.onComplete = $.isFunction(onComplete) ? onComplete : false;

			$(this).each(function() {
				function showTree(c, t) {
					$(c).addClass('wait');
					$(".jqueryFileTree.start").remove();
					$.get(o.script, { dir: t }, function(data) {
						if (o.loadEntireTree) {
							$(c).html(appendData(c, data));
							bindTree(c);
							var leaf = $.cookie('selected_node');
							$('a[rel=' + leaf + ']').addClass('selected');
							var vertex_list = $.cookie('current_branch');
							if (vertex_list) showNodes(vertex_list);
							if(o.onComplete) o.onComplete.call(c);
						} else {
							$(c).find('.start').html('');
							$(c).removeClass('wait').append(data);
							if (o.root == t) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
							bindTree(c);
						}
					});
				}

				function showNodes(vertex_list) {
					var remove_class = 'collapsed';
					var add_class = 'expanded';

					if (o.startExpanded) {
						remove_class = 'expanded';
						add_class = 'collapsed';
					}

					var vertexes = vertex_list.split(':');
					for (var i = 0; i < vertexes.length; i++) {
						var node = $('.startTree').find('a[rel=' + vertexes[i] + ']');
						node.parent().find('ul:first').removeClass(remove_class).addClass(add_class);
					}
				}

				function appendData(c, data) {
					$(c).find('.start').html('');
					$(c).removeClass('wait');

					var vertex_list = $.cookie('current_branch');
					var list = $('<ul/>').addClass('jqueryFileTree startTree');

					if (data['start']) {
						var starting_nodes_counter = data['start'].length;
						if (!vertex_list) {
							storeNodes('');
							var cl = 'expanded';
							list.addClass(cl)
						}

						for (var i = 0; i < starting_nodes_counter; i++) {
							var current_node = data['start'][i];
							var rel = current_node.rel;
							var url = '#';
							if (current_node.url) url = current_node.url;

							var img_class = current_node.kind == 'node' ? o.nodeClass : o.leafClass;
							var li = $('<li>').addClass(img_class);
							$('<a>').attr({ rel: rel, href: url}).text(current_node.name).appendTo(li);

							if (rel && data[rel]) {
								var cl = (o.startExpanded ? 'expanded' : 'collapsed');
								li.append(appendDataRecursive(data, rel, cl));
							}
							list.append(li);
						}
					}
					return list;
				}

				function appendDataRecursive(data, rel_n, visibility) {
					var list = $('<ul/>').addClass('jqueryFileTree ' + visibility);

					if (data[rel_n]) {
						for (var i = 0; i < data[rel_n].length; i++) {
							var current_node = data[rel_n][i];
							var rel = current_node.rel;
							var url = '#';
							if (current_node.url) url = current_node.url;
							var img_class = current_node.kind == 'node' ? o.nodeClass : o.leafClass;

							var li = $('<li>').addClass(img_class);
							$('<a>').attr({ rel: rel, href: url}).text(current_node.name).appendTo(li);
							if (rel && data[rel]) li.append(appendDataRecursive(data, rel, visibility));
							list.append(li);
						}
					}
					return list;
				}

				function treeBinding(self) {
					if ($(self).parent().hasClass('directory')) {
						if ($(self).parent().hasClass('collapsed')) {
							// Expand
							if (!o.multiFolder) {
								$(self).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
								$(self).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
							}
							$(self).parent().find('UL').remove(); // cleanup
							showTree($(self).parent(), escape($(self).attr('rel').match(/.*\//)));
							$(self).parent().removeClass('collapsed').addClass('expanded');
						} else {
							// Collapse
							$(self).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
							$(self).parent().removeClass('expanded').addClass('collapsed');
						}
					} else {
						handleLeafEvt($(self).attr('rel'));
					}
					return false;
				}

				function fullTreeBinding(self) {
					if ($(self).parent().hasClass(o.nodeClass)) {
						var vertex_list = $.cookie('current_branch');
						vertex_list = vertex_list.split(':');
						var current_node = $(self).attr('rel') + '';
						if ($(self).parent().find('ul:first').hasClass('collapsed')) {
							var selected_node = $.cookie('selected_node');
							vertex_list = o.startExpanded ? removeNode(current_node, vertex_list) : addNode(current_node, vertex_list);
							storeNodes(vertex_list);
							$(self).parent().find('ul:first').removeClass('collapsed').addClass('expanded');
							if (current_node != selected_node) {
								$('.startTree').find('a').removeClass('selected');
								$(self).addClass('selected');
								storeSelected(self.rel);
								handleNodeEvt($(self));
							}
						} else if ($(self).parent().find('ul:first').hasClass('expanded')) {
							if ($(self).hasClass('selected')) {
								vertex_list = o.startExpanded ? addNode(current_node, vertex_list) : removeNode(current_node, vertex_list);
								storeNodes(vertex_list);
								$(self).parent().find('ul:first').removeClass('expanded').addClass('collapsed');
							} else {
								$('.startTree').find('a').removeClass('selected');
								$(self).addClass('selected');
								storeSelected(self.rel);
								handleNodeEvt($(self));
							}
						}
					} else {
						$('.startTree').find('a').removeClass('selected');
						$(self).addClass('selected');
						storeSelected(self.rel);
						handleLeafEvt($(self));
					}
					return false;
				}

				function bindTree(t) {
					$(t).find('LI A').bind(o.folderEvent, function() {
						var self = this;
						o.loadEntireTree ? fullTreeBinding(self) : treeBinding(self);
					});
					// Prevent A from triggering the # on non-click events
					if (o.folderEvent.toLowerCase != 'click') $(t).find('LI A').bind('click', function() {
						return false;
					});
				}

				function storeNodes(vertex_list) {
					$.cookie('current_branch', vertex_list, { 'path': '/'});
				}

				function storeSelected(selected_node_rel) {
					$.cookie('selected_node', selected_node_rel, { 'path': '/'});
				}

				function removeNode(current_node, vertex_list) {
					vertex_list = $.grep(vertex_list, function(val) {
						return val != current_node;
					});
					return vertex_list.join(':');
				}

				function addNode(current_node, vertex_list) {
					if ($.inArray(current_node + "", vertex_list) == -1) {
						vertex_list = vertex_list.join(':') + ':' + current_node;
					}
					return vertex_list;
				}

				// Loading message
				$(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '</li></ul>');
				// Get the initial file list
				showTree($(this), escape(o.root));
			});
		}
	});
})(jQuery);
