(function(Shout,jQuery)
{

jQuery.extend(Shout.fn,
	{
		tree: function(nodeSelector,contentSelector, params)
		{
			var shoutObj = this;

			if(!this.nodeEl.data('TreeView'))
			{
				this.Tree = new Tree(null,this,nodeSelector,contentSelector, params);
				this.Tree.name = this.nodeEl.attr('id');

				this.nodeEl.data('TreeView',this.Tree);

				this.nodeEl.bind('emptytree', function(event,data)
				{
					shoutObj.nodeEl.html('<li>No matches found for criteria.</li>');
				});
			}
			else
			{
				this.Tree = this.nodeEl.data('TreeView');
			}


			return this;
		}
	}
);


var Tree = function(treeRoot, obj, nodeSelector,contentSelector, params)
{
	if(!treeRoot)
		treeRoot = this;

	return this.init(treeRoot,obj,nodeSelector,contentSelector,params);
};


Shout.fn.Tree = Tree.prototype = {
	// Override this function with your own via "monkeypatching" of the Tree object.
	getBranch: null,
	init: function(root, obj, nodeSelector,contentSelector,params)
	{
		var self = this;

		this.treeElements = {};

		this.contentSelector = contentSelector;
		this.nodeSelector = nodeSelector;

		this.lastNestEl = null;
		this.currentObj = obj;

		this.treeRoot = root;

		this.segregationX = 1000;
		this.segregationY = 100;

		// For saving tree state between page loads.
		this.state = [];

		this.filterText = '';

		// this.drop(obj,obj.nodeEl.find(contentSelector));
		this.treeRoot.treeElements[obj.shoutId] = obj;

		if(!params)
			params = {};

//		if(params.name)
//		{
//			this.name = params.name;
//		}
//		else
//		{
//			this.name = 'tree';
//		}

		// TODO ::JACOB wrong place for this.
		this.params = jQuery.extend(
		{
			filterMode:'all',
			callbackTreshold: 500
		},params);


		this.make(this.currentObj.nodeEl.find(this.nodeSelector));

		return this;
	},

	make : function($elements)
	{
		var self = this;

		var treeRoot = this.treeRoot;

		$elements.each(function()
		{
			var $treeElement = jQuery(this).addClass('sui-tree-node');

			$treeElement.find(' > ul').addClass('sui-tree-nested');

			self.addToggle($treeElement);


		});


		return this;
	},

	addToggle : function($treeElement)
	{
		var	self = this;

		if($treeElement && ( this.hasNest($treeElement) || this.isDynamic($treeElement) ) )
		{

			if(!$treeElement.find('> .sui-tree-toggle').length)
			{

				var $toggleEl = jQuery('<div class = "sui-tree-toggle ui-icon ui-icon-minus"></div>');

				$toggleEl.click(function(){
					self.toggle($treeElement);
				});

				$treeElement.find(' > .sui-tree-item > .sui-tree-text').bind('click.sui-toggle',function()
				{
					self.toggle($treeElement);
				}).addClass('sui-clickable');

				$treeElement.append($toggleEl);
			}

			if(this.isDynamic($treeElement))
			{
				this.collapse($treeElement);
			}
		}

		if(this && this.treeRoot)
		{
			if(this.hasNest($treeElement) && !$treeElement.find(' > ul ').length)
			{
				$treeElement.find('> .sui-tree-toggle').remove();
			}
		}
	},

	hasNest: function($treeElement)
	{
		if( $treeElement.find(' > ul').length > 0 )
		{
			return true;
		}

		return false;
	},

	toggle : function($treeElement)
	{
		if(this.hasNest($treeElement) || this.isDynamic($treeElement) )
		{
			if($treeElement.find(' > ul').hasClass('collapsed'))
			{
				this.expand($treeElement);
			}
			else
			{
				this.collapse($treeElement);
			}
		}
	},

	collapseAll : function()
	{
		var self = this;

		jQuery.each(this.currentObj.nodeEl.find('li'), function()
		{
			self.collapse(jQuery(this));
		});
	},

	expandAll : function()
	{
		var self = this;

		jQuery.each(this.currentObj.nodeEl.find('li'), function()
		{
			self.expand(jQuery(this), true);
		});

	},

	addState: function($treeElement)
	{
		if(jQuery.inArray($treeElement.attr('id'),this.state) == -1)
		{
			this.state.push($treeElement.attr('id'));
		}
	},

	removeState: function($treeElement)
	{
		var elementId = $treeElement.attr('id');

		this.state = jQuery.grep(this.state,function(el,i)
		{
			if(el != elementId)
			{
				return true;
			}
		});
	},

	saveState: function()
	{
		var self = this;
		var result = {};
		result['sui-tree-'+this.name] = [];

		jQuery.each(this.state,function(i, el)
		{
			result['sui-tree-'+self.name].push(el);
		});

		jQuery.bbq.pushState(result);
	},

	setExpandedClass: function($treeElement){
		$treeElement.find(' > ul').removeClass('collapsed');
		$treeElement.find('> .sui-tree-toggle')
			.removeClass('ui-icon-plus  ui-icon-loading')
			.addClass('ui-icon-minus');
	},

	setCollapsedClass: function($treeElement){
		$treeElement.find(' > ul').addClass('collapsed');
		$treeElement.find('> .sui-tree-toggle')
			.removeClass('ui-icon-minus ui-icon-loading')
			.addClass('ui-icon-plus');
	},

	setLoadingClass: function($treeElement){
		$treeElement.find('> .sui-tree-toggle')
			.addClass('ui-icon-loading');
	},

	expand : function($treeElement, all)
	{
		var self = this;

		if(this.isDynamic($treeElement))
		{
			this.setLoadingClass($treeElement);
			this.getBranch($treeElement,
				function(){
					self.setExpandedClass($treeElement);
				},
				all
			);
		}
		else if (this.hasNest($treeElement) )
		{
			this.setExpandedClass($treeElement);
		}

		//this.addState($treeElement);
		//this.saveState();
	},

	collapse : function($treeElement)
	{

		if(this.hasNest($treeElement) || this.isDynamic($treeElement))
		{
			this.setCollapsedClass($treeElement);
		}

		//this.removeState($treeElement);
		//this.saveState();
	},

	destroy : function()
	{
		var treeRoot = this.treeRoot;
		treeRoot.treeElements = null;
		treeRoot.lastNestEl = null;

		treeRoot.currentObj.nodeEl.empty();

		jQuery('#'+this.name).data('TreeView',null);
	},

	isDynamic: function($treeElement)
	{
		return $treeElement.find('> input.sui-query').length > 0;
	}
};

Shout.fn.Tree.init.prototype = Shout.fn.Tree;

})(Shout,jQuery);





