/*
 * jQuery Tree Node Object @VERSION
 *
 * Copyright (c) 2011 excentrics.ru
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses
 *
 * Depends:
 *  jquery.excentrics.tree.core.js
 */
(jQuery.TreeNode || jQuery.tree && (function($){

// Construct a tree node object
$.TreeNode = function(element, options){
	if (typeof this === 'function') {
		return new $.TreeNode(element, options);
	}
	
	var settings = $.extend({
		parent: null,
		children: null
	}, options || {});
	
	var children = settings.children;
	if (children && children.length) {
		// Copy children
		var i;
		i = this.length = children.length;
		while (i--) {
			var child = children[i];
			child._parent = this;
			this[i] = child;
		}
	} else {
		this.length = 0;
	}
	
	this.element = element;
	this._parent = settings.parent;

};

$.TreeNode.fn = $.TreeNode.prototype = {
	
	treeNode: "@VERSION",
	
	children: function(){
		return $.makeArray(this);
	},
	
	parent: function(){
		return this._parent;
	},
	
	hasChildren: function(){
		return !!this.length;
	},
	
	descendants: function(_descendants){
		if (!_descendants) {
			_descendants = [];
		}	
		var n = this.length;
		for (var i = 0; i < n; i++) {
			var child = this[i];
			_descendants.push(child);
			child.descendants(_descendants);
		}
		return _descendants;
	},
	
	ancestors: function(){
		var _ancestors = [],
			node = this,
			parent;
		while (parent = node._parent) {
			node = parent;
			_ancestors.push(node);
		}
		return _ancestors;
	},
	
	findNode: function(node){
		var _descendants = this.descendants(),
		i = _descendants.length;
		while (i--) {
			if (_descendants[i].element == node.element) {
				return _descendants[i];
			}
		}
		return this.element == node.element ? this : null;
	},
	
	each: function(preorderCallback, postorderCallback, extra){
		if (!extra) {
			extra = {};
		}
		
		if (typeof preorderCallback === 'function') {
			if (preorderCallback.call(this, extra) === false) {
				return false;
			}
		}
		
		var	n = this.length;		
		for (var i = 0; i < n; i++) {
			if (this[i].each(preorderCallback, postorderCallback, extra) === false) {
				return false;
			}
		}	
		
		if (typeof postorderCallback === 'function') {			
			if (postorderCallback.call(this, extra) === false) {
				return false;
			}
		}
	}
	
}

// Check whether the given argument is a valid tree node object
$.TreeNode.isInstance = function(node) {
	return node && typeof node === 'object' && node.treeNode === $.TreeNode.fn.treeNode;
};

})(jQuery)
);


