Tree.Item = Class.create();
Tree.Item.prototype = {
	initialize: function(id, tree, parent, ajaxUpdate) {
		this.parent = parent;
		this.tree = tree;
		this.elements = {};
		this.elementID = {};
		
		var element;
		
		if (typeof id == 'string') {
			element = $(id);
			this.id = id;
		} else {
			element = id;
			this.id = element.id;
		}
		
		element.object = this;

		this.elementID.children = this.id + Tree.ID_DEVIDER + Tree.ID_CHILDS_ROW;
		this.elementID.mainRow = this.id + Tree.ID_DEVIDER + Tree.ID_MAIN_ROW;
		this.elementID.handle = this.id + Tree.ID_DEVIDER + Tree.ID_HANDLE;
		this.elementID.handleImgExpanded = this.elementID.handle + Tree.ID_DEVIDER + Tree.ID_HANDLE_IMG_EXPANDED;
		this.elementID.handleImgCollapsed = this.elementID.handle + Tree.ID_DEVIDER + Tree.ID_HANDLE_IMG_COLLAPSED;
		this.elementID.icon = this.id + Tree.ID_DEVIDER + Tree.ID_ICON;
		this.elementID.text = this.id + Tree.ID_DEVIDER + Tree.ID_TEXT;
		
		this.getElements(element, ajaxUpdate);

		this.eventSelectionClick = this.toggleSelection.bindAsEventListener(this);
		this.eventMouseOut = this.processMouseOut.bindAsEventListener(this);
		this.eventMouseOver = this.processMouseOver.bindAsEventListener(this);

		if (this.onContextMenu) {
			this.eventRightClick = this.onContextMenu.bindAsEventListener();
		}

		this.observeEvents(element);
	},

	destroy: function() {
		if (this == this.tree.selectionManager.activeItem) {
			this.tree.selectionManager.activeItem = null;
		}
		
		for (var i = 0; i < this.childs.length; i++) {
			this.childs[i].destroy();
		}
		
		this.childs = null;
	},

	observeEvents: function(element) {
		var eIcon = null;
		var eText = null;
		if ("NETSCAPE" == RichFaces.navigatorType()) {
			eIcon = $(this.elementID.icon); 
			eText = $(this.elementID.text); 
		} else {
			var cells = element.rows[0].cells;
			//seeking by id seems to be miserably slow in IE than by index
			eIcon = cells[this.elementID.icon];
			eText = cells[this.elementID.text];
		}
		if (eIcon) {
			Event.observe(eIcon, "mousedown", this.eventSelectionClick);
			Event.observe(eIcon, "mouseout", this.eventMouseOut);
			Event.observe(eIcon, "mouseover", this.eventMouseOver);
			if (this.eventRightClick) {
				eIcon.oncontextmenu = this.eventRightClick;
			}			
		}
		if (eText)
		{
			Event.observe(eText, "mousedown", this.eventSelectionClick);
			Event.observe(eText, "mouseout", this.eventMouseOut);
			Event.observe(eText, "mouseover", this.eventMouseOver);
			if (this.eventRightClick) {
				eText.oncontextmenu = this.eventRightClick;
			}			
		}

		if (this.tree.switchType=="client" && this.childs.length > 0) {
			this.eventCollapsionClick = this.toggleCollapsion.bindAsEventListener(this);
			
			var handleElt = this.tree.toggleOnClick ? this.elementID.mainRow : this.elementID.handle;
			Event.observe(handleElt, "click", this.eventCollapsionClick);
		}
	},

	getElements: function(element, ajaxUpdate) {
		this.childs = [];

		/*var contextMenu = Richfaces.getNSAttribute("oncontextmenu", $(this.elementID.icon));
		if (contextMenu && contextMenu.length > 0) {
			this.onContextMenu = new Function(contextMenu + "; return true;");
		}*/
		
		var childsTd = element.nextSibling;//$(this.elementID.children);
		
		if (ajaxUpdate && this.tree.showConnectingLines) {
			var cell = element.rows[0].cells[0];
			if (cell.style && cell.style.removeExpression) {
				cell.style.backgroundImage = cell.currentStyle.backgroundImage;
				cell.style.removeExpression('backgroundImage');
			}
	
			if (childsTd) {
				if (childsTd.style && childsTd.style.removeExpression) {
					childsTd.style.backgroundImage = childsTd.currentStyle.backgroundImage;
					childsTd.style.removeExpression('backgroundImage');
				}
			}
		}

		if (childsTd) {
			var child = childsTd.firstChild;
			while ( child != null )
			{
                if (child.nodeType == 1 && child.tagName.toLowerCase() == "table") {
                    this.addChild(new Tree.Item(child, this.tree, this));
                }
                child = child.nextSibling;
            }
            /*
            for (var i = 0; i < childsTd.childNodes.length; i++) {
				var child = childsTd.childNodes[i];
				if (child.nodeType == 1 && child.tagName.toLowerCase() == "table") {
					this.addChild(new Tree.Item(child.id, this.tree, this));
				}
			}
			*/
		}
	},

	addChild: function(child) {
		this.childs.push(child);
	},

	fireExpansionEvent: function() {
		var props = new Object();
		props[Richfaces.TreeExpandEvent] = true;
		props["expandedNode"] = this.id;
		props["treeItem"] = this;
		Richfaces.createEvent("click", this.tree.element, null, props).fire();
	},

	fireCollapsionEvent: function() {
		var props = new Object();
		props[Richfaces.TreeCollapseEvent] = true;
		props["collapsedNode"] = this.id;
		props["treeItem"] = this;
		Richfaces.createEvent("click", this.tree.element, null, props).fire();
	},

	toggleCollapsion: function() {

		var row=this.id + Tree.ID_DEVIDER + Tree.ID_CHILDS_ROW; 
		if (this.hasChilds()) Element.toggle(row);

		// Rerender main row to avoid bad representation in Opera and Konqueror/Safari
		var e = $(this.elementID.mainRow)
		if (e) {
			Element.hide(e);
			Element.show(e);
		}
		
		var nodeStateInput = $(this.id + "NodeExpanded");

		var eIcon = $(this.elementID.icon);

		if (this.isCollapsed()) {
			Element.hide(this.elementID.handleImgExpanded);
			Element.show(this.elementID.handleImgCollapsed);
			if( eIcon && Element.hasClassName(eIcon, Tree.CLASS_ITEM_EXPANDED)) {
				Element.removeClassName(eIcon, Tree.CLASS_ITEM_EXPANDED);
				Element.addClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED);
			}

			if (nodeStateInput) {
				nodeStateInput.value = "false";
			}

			this.fireCollapsionEvent();
		} else {
			Element.show(this.elementID.handleImgExpanded);
			Element.hide(this.elementID.handleImgCollapsed);
			if(eIcon && Element.hasClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED)) {
				Element.removeClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED);
				Element.addClassName(eIcon, Tree.CLASS_ITEM_EXPANDED);
			}

			if (nodeStateInput) {
				nodeStateInput.value = "true";
			}

			this.fireExpansionEvent();
		}

	},

	getRichAttribute: function(name) {
		return Richfaces.getNSAttribute(name, $(this.elementID.icon));
	},

	collapse: function() {
		if (!this.isCollapsed() && this.tree.switchType!="client") {
			var handleElt = $(this.tree.toggleOnClick ? this.elementID.mainRow : this.elementID.handle);
			if (handleElt) {
				handleElt.onclick();
			}
		}

		if (this.hasChilds() && !this.isCollapsed()) {
			Element.hide(this.elementID.children);
			Element.hide(this.elementID.handleImgExpanded);
			Element.show(this.elementID.handleImgCollapsed);
			var eIcon = $(this.elementID.icon);		
			if(eIcon && Element.hasClassName(eIcon, Tree.CLASS_ITEM_EXPANDED)) {
				Element.removeClassName(eIcon, Tree.CLASS_ITEM_EXPANDED);
				Element.addClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED);
			}
		}

		this.fireCollapsionEvent();
	},

	expand: function() {
		if (this.isCollapsed() && this.tree.switchType!="client") {
			var handleElt = $(this.tree.toggleOnClick ? this.elementID.mainRow : this.elementID.handle);
			if (handleElt) {
				handleElt.onclick();
			}
		}

		if (this.hasChilds() && this.isCollapsed()) {
			Element.show(this.elementID.children);
			Element.show(this.elementID.handleImgExpanded);
			Element.hide(this.elementID.handleImgCollapsed);
			var eIcon = $(this.elementID.icon);
			if(eIcon && Element.hasClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED)) {
				Element.removeClassName(eIcon, Tree.CLASS_ITEM_COLLAPSED);
				Element.addClassName(eIcon, Tree.CLASS_ITEM_EXPANDED);
			}
		}

		this.fireExpansionEvent();
	},

	isCollapsed: function() {
		var e = $(this.elementID.children);
		if (e) {
			return e.style.display == "none";
		} else {
			return true;
		}
	},

	processMouseOut: function(e) {
		if (this.isMouseIn) {
			this.isMouseIn = false;
			var eText = $(this.elementID.text);
			var hClass = Richfaces.getNSAttribute("highlightedclass", eText);
			if (hClass) {
				var classNames = hClass.split(' ')
				for (var i = 0; i < classNames.length; i++) {
					Element.removeClassName(eText, classNames[i]);
				}
				if (window.drag){
					this.dragLeave(e);
				}
			}
		}
	},

	processMouseOver: function(e) {
		if(!this.isMouseIn) {
			this.isMouseIn = true;
			var eText = $(this.elementID.text);
			var hClass = Richfaces.getNSAttribute("highlightedclass", eText);
			if (hClass) {
				var classNames = hClass.split(' ')
				for (var i = 0; i < classNames.length; i++) {
					Element.addClassName(eText, classNames[i]);
				}
				if (window.drag) {
					this.dragEnter(e);
				}
			}
		}
	},

	toggleSelection: function(e) {
		if (e && !e[Richfaces.TreeSelectEvent] && !Richfaces.eventIsSynthetic(e)) {
			if (e && e.type == "mousedown" /* can be keydown */) {
				if(Event.isLeftClick(e)) {
				  var src = Event.element(e);
				   if(src.tagName && 
				   		/^(input|select|option|button|textarea)$/i.test(src.tagName))
							return;

					Event.stop(e);
				} else {
					//do not process non-left clicks
					return ;
				}
			}

			var props = new Object();
			props[Richfaces.TreeSelectEvent] = true;
			props["originatingEventType"] = e.type;
			props["treeItem"] = this;
			props["selectedNode"] = this.id;
			var evt = Richfaces.createEvent("click", this.tree.element, null, props);
			evt.fire();

			return !evt.event["cancelSelection"];
		} else {
			var activeItem = this.tree.selectionManager.activeItem;
			if (activeItem) {
				activeItem.deselect();
			}

			/*
			var attr = this.elements.text.attributes;
			var s = "";
			for (var i = 0; i < attr.length; i++) {
				s += attr[i].nodeName + ": " + attr[i].nodeValue + ";  ";
			}

			alert(s);
			*/
			
			var eText = $(this.elementID.text);
			var sClass = Richfaces.getNSAttribute("selectedclass", eText);
			if (sClass) {

				var classNames = sClass.split(' ')
				for (var i = 0; i < classNames.length; i++) {
					Element.addClassName(eText, classNames[i]);
				}
				this.tree.input.value = this.id;
				this.tree.selectionManager.activeItem = this;

				if (this.tree.options.onSelection) this.tree.options.onSelection(this.id);
				this.tree.showNode(eText.parentNode);

				if (e && e["originatingEventType"] == "mousedown" /* can be keydown */) {
					this.startDrag(e);
				}
			}

			return true;
		}
	},

	isSelected: function() {
		return Element.hasClassName(this.elementID.text, Tree.CLASS_ITEM_SELECTED);
	},

	deselect: function() {
		var eText = $(this.elementID.text);
		var sClass = Richfaces.getNSAttribute("selectedclass", eText);
		if (sClass) {
			var classNames = sClass.split(' ')
			for (var i = 0; i < classNames.length; i++) {
				Element.removeClassName(eText, classNames[i]);
			}
		}
	},

	next: function() {
		var children = this.parent.childs;
		
		for (var i = 0; i < children.length - 1; i++) {
			if (children[i] == this) {
				return children[i + 1];
			}
		}
		
		return this;
	},

	previous: function() {
		var children = this.parent.childs;

		for (var i = 1; i < children.length; i++) {
			if (children[i] == this) {
				return children[i - 1];
			}
		}

		return this;
	},

	hasChilds: function() {
		return this.childs.length > 0;
	}
}
