/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.widget.TreeNodeV3");

dojo.require("dojo.html.*");
dojo.require("dojo.event.*");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.TreeWithNode");

dojo.widget.defineWidget(
	"dojo.widget.TreeNodeV3",
	[dojo.widget.HtmlWidget, dojo.widget.TreeWithNode],
	function() {
		this.actionsDisabled = [];
	        this.object = {};
	},
{
	tryLazyInit: true,

	/*
	 * Basic actions one can perform on nodes and, some(addchild) on trees
	 */
	actions: {
		MOVE: "MOVE",
    	DETACH: "DETACH",
    	EDIT: "EDIT",
    	ADDCHILD: "ADDCHILD",
		SELECT: "SELECT"
	},


	labelClass: "",
	contentClass: "",

	expandNode: null,
	labelNode: null,

    /**
     *	can't call it nodeType cause of IE problems
     */
	nodeDocType: "",
    selected: false,

	getnodeDocType: function() {
		return this.nodeDocType;
	},

	cloneProperties: ["actionsDisabled","tryLazyInit","nodeDocType","objectId","object",
		   "title","isFolder","isExpanded","state"],


	/**
	 * copy cloneProperties with recursion into them
	 * contains "copy constructor"
	 */
	clone: function(deep) {
		var ret = new this.constructor();

		//dojo.debug("start cloning props "+this);

		for(var i=0; i<this.cloneProperties.length; i++) {
			var prop = this.cloneProperties[i];
			//dojo.debug("cloning "+prop+ ":" +this[prop]);
			ret[prop] = dojo.lang.shallowCopy(this[prop], true);
		}

		if (this.tree.unsetFolderOnEmpty && !deep && this.isFolder) {
			ret.isFolder = false;
		}

		//dojo.debug("cloned props "+this);

		ret.toggleObj = this.toggleObj;

		dojo.widget.manager.add(ret);

		ret.tree = this.tree;
		ret.buildRendering({},{});
		ret.initialize({},{});

		if (deep && this.children.length) {
			//dojo.debug("deeper copy start");
			for(var i=0; i<this.children.length; i++) {
				var child = this.children[i];
				//dojo.debug("copy child "+child);
				if (child.clone) {
					ret.children.push(child.clone(deep));
				} else {
					ret.children.push(dojo.lang.shallowCopy(child, deep));
				}
			}
			//dojo.debug("deeper copy end");
			ret.setChildren();
		}



		return ret;
	},


	markProcessing: function() {
		this.markProcessingSavedClass = dojo.html.getClass(this.expandNode);
		dojo.html.setClass(this.expandNode, this.tree.classPrefix+'ExpandLoading');
	},

	unmarkProcessing: function() {
		dojo.html.setClass(this.expandNode, this.markProcessingSavedClass);
	},




	/**
	 * get information from args & parent, then build rendering
	 */
	buildRendering: function(args, fragment, parent) {
		//dojo.debug("Build for "+args.toSource());

		if (args.tree) {
			this.tree = dojo.lang.isString(args.tree) ? dojo.widget.manager.getWidgetById(args.tree) : args.tree;
		} else if (parent && parent.tree) {
			this.tree = parent.tree;
		}

		if (!this.tree) {
			dojo.raise("Can't evaluate tree from arguments or parent");
		}


		//dojo.profile.start("buildRendering - cloneNode");

		this.domNode = this.tree.nodeTemplate.cloneNode(true);
		this.expandNode = this.domNode.firstChild;
		this.contentNode = this.domNode.childNodes[1];
		this.labelNode = this.contentNode.firstChild;

		if (this.labelClass) {
			dojo.html.addClass(this.labelNode, this.labelClass);
		}

		if (this.contentClass) {
			dojo.html.addClass(this.contentNode, this.contentClass);
		}


		//dojo.profile.end("buildRendering - cloneNode");


		this.domNode.widgetId = this.widgetId;

		//dojo.profile.start("buildRendering - innerHTML");
		this.labelNode.innerHTML = this.title;
		//dojo.profile.end("buildRendering - innerHTML");

	},


	isTreeNode: true,


	object: {},

	title: "",

	isFolder: null, // set by widget depending on children/args

	contentNode: null, // the item label

	expandClass: "",


	isExpanded: false,


	containerNode: null,


	getInfo: function() {
		// No title here (title may be widget)
		var info = {
			widgetId: this.widgetId,
			objectId: this.objectId,
			index: this.getParentIndex()
		}

		return info;
	},

	setFolder: function() {
		//dojo.debug("SetFolder in "+this);
		this.isFolder = true;
		this.viewSetExpand();
		if (!this.containerNode) { // maybe this node was unfolderized and still has container
			this.viewAddContainer(); // all folders have container.
		}
		//dojo.debug("publish "+this.tree.eventNames.setFolder);
		dojo.event.topic.publish(this.tree.eventNames.afterSetFolder, { source: this });
	},



	initialize: function(args, frag, parent) {

		//dojo.profile.start("initialize");

		/**
		 * first we populate current widget from args,
		 * then use its data to initialize
		 * args may be empty, all data inside widget for copy constructor
		 */
		if (args.isFolder) {
			this.isFolder = true;
		}

		if (this.children.length || this.isFolder) {
			//dojo.debug("children found");
			//dojo.debug(this.children);
			//dojo.debug("isFolder "+args.isFolder);

			// viewSetExpand for Folder is set here also
			this.setFolder();
		} else {
			// set expandicon for leaf
			this.viewSetExpand();
		}

		for(var i=0; i<this.actionsDisabled.length;i++) {
			this.actionsDisabled[i] = this.actionsDisabled[i].toUpperCase();
		}
		//dojo.debug("publish "+this.tree.eventNames.changeTree);



		dojo.event.topic.publish(this.tree.eventNames.afterChangeTree, {oldTree:null, newTree:this.tree, node:this} );


		//dojo.profile.end("initialize");

		//dojo.debug("initialize out "+this);
		//dojo.debug(this+" parent "+parent);
	},

	unsetFolder: function() {
		this.isFolder = false;
		this.viewSetExpand();
		dojo.event.topic.publish(this.tree.eventNames.afterUnsetFolder, { source: this });
	},


	insertNode: function(parent, index) {

		if (!index) index = 0;
		//dojo.debug("insertNode "+this+" parent "+parent+" before "+index);

		if (index==0) {
			dojo.html.prependChild(this.domNode, parent.containerNode);
		} else {
			dojo.html.insertAfter(this.domNode, parent.children[index-1].domNode);
		}
	},

	updateTree: function(newTree) {

		if (this.tree === newTree) {
			return;
		}

		var oldTree = this.tree;


		dojo.lang.forEach(this.getDescendants(),
			function(elem) {
				elem.tree = newTree;
		});

		/**
		 * UNTESTED
		 * changes class prefix for all domnodes when moving between trees
		 */
		if (oldTree.classPrefix != newTree.classPrefix) {
			var stack = [this.domNode]
			var elem;
			var reg = new RegExp("(^|\\s)"+oldTree.classPrefix, "g");

			while (elem = stack.pop()) {
				for(var i=0; i<elem.childNodes.length; i++) {
					var childNode = elem.childNodes[i]
					if (childNode.nodeDocType != 1) continue;
					// change prefix for classes
					dojo.html.setClass(childNode, dojo.html.getClass(childNode).replace(reg, '$1'+newTree.classPrefix));
					stack.push(childNode);
				}
			}

		}

		var message = {oldTree:oldTree, newTree:newTree, node:this}

		dojo.event.topic.publish(this.tree.eventNames.afterChangeTree, message );
		dojo.event.topic.publish(newTree.eventNames.afterChangeTree, message );


	},


	/**
	 * called every time the widget is added with createWidget or created wia markup
	 * from addChild -> registerChild or from postInitialize->registerChild
	 * not called in batch procession
	 * HTML & widget.createWidget only
	 * Layout MUST be removed when node is detached
	 *
	 */
	addedTo: function(parent, index, dontPublishEvent) {
		//dojo.profile.start("addedTo");
		//dojo.debug(this + " addedTo "+parent+" index "+index);
		//dojo.debug(parent.children);
		//dojo.debug(parent.containerNode.innerHTML);

		//dojo.debug((new Error()).stack);


		if (this.tree !== parent.tree) {
			this.updateTree(parent.tree);
		}

		if (parent.isTreeNode) {
			if (!parent.isFolder) {
				//dojo.debug("folderize parent "+parent);
				parent.setFolder();
				parent.state = parent.loadStates.LOADED;
			}
		}


		var siblingsCount = parent.children.length;

		// setFolder works BEFORE insertNode
		this.insertNode(parent, index);


		this.viewAddLayout();


		//dojo.debug("siblings "+parent.children);

		if (siblingsCount > 1) {
			if (index == 0 && parent.children[1] instanceof dojo.widget.Widget) {
				parent.children[1].viewUpdateLayout();
			}
			if (index == siblingsCount-1 && parent.children[siblingsCount-2] instanceof dojo.widget.Widget) {
				parent.children[siblingsCount-2].viewUpdateLayout();
			}
		} else if (parent.isTreeNode) {
			// added as the first child
			//dojo.debug("added as first");
			parent.viewSetHasChildren();
		}

		if (!dontPublishEvent) {

			var message = {
				child: this,
				index: index,
				parent: parent
			}

			dojo.event.topic.publish(this.tree.eventNames.afterAddChild, message);
		}

		//dojo.profile.end("addedTo");


	},

	/**
	 * Fast program-only hacky creation of widget
	 *
	 */
	createSimple: function(args, parent) {
		// I pass no args and ignore default controller
		//dojo.profile.start(this.widgetType+" createSimple");
		//dojo.profile.start(this.widgetType+" createSimple constructor");
		if (args.tree) {
			var tree = args.tree;
		} else if (parent) {
			var tree = parent.tree;
		} else {
			dojo.raise("createSimple: can't evaluate tree");
		}
		tree = dojo.widget.byId(tree);

		//dojo.debug(tree);

		var treeNode = new tree.defaultChildWidget();
		//dojo.profile.end(this.widgetType+" createSimple constructor");

		//dojo.profile.start(this.widgetType+" createSimple mixin");
		for(var x in args){ // fastMixIn
			treeNode[x] = args[x];
		}


		//dojo.profile.end(this.widgetType+" createSimple mixin");


		// HtmlWidget.postMixIn
		treeNode.toggleObj = dojo.lfx.toggle[treeNode.toggle.toLowerCase()] || dojo.lfx.toggle.plain;

		//dojo.profile.start(this.widgetType + " manager");
		dojo.widget.manager.add(treeNode);
		//dojo.profile.end(this.widgetType + " manager");

		//dojo.profile.start(this.widgetType + " buildRendering");
		treeNode.buildRendering(args, {}, parent);
		//dojo.profile.end(this.widgetType + " buildRendering");

		treeNode.initialize(args, {}, parent);

		//dojo.profile.end(this.widgetType+"createSimple");
		if (treeNode.parent) {
			delete dojo.widget.manager.topWidgets[treeNode.widgetId];
		}

		return treeNode;
	},



	// can override e.g for case of div with +- text inside
	viewUpdateLayout: function() {
		//dojo.profile.start("viewUpdateLayout");
		//dojo.debug("UpdateLayout in "+this);

		this.viewRemoveLayout();
		this.viewAddLayout();
		//dojo.profile.end("viewUpdateLayout");
	},


	viewAddContainer: function() {
		// make controller only if children exist
		this.containerNode = this.tree.containerNodeTemplate.cloneNode(true);
		this.domNode.appendChild(this.containerNode);
	},
	/*
	viewRemoveContainer: function() {
		// make controller only if children exist
		this.domNode.removeChild(this.containerNode);
		this.containerNode = null;
	},
	*/

	viewAddLayout: function() {
		//dojo.profile.start("viewAddLayout");
		//dojo.debug("viewAddLayout in "+this);

		if (this.parent["isTree"]) {
			//dojo.debug("Parent isTree => add isTreeRoot");

			// use setClass, not addClass for speed
			dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode) + ' '+this.tree.classPrefix+'IsRoot')
		}
		//dojo.debug(this.parent.children.length);
		//dojo.debug(this.parent.children[this.parent.children.length-1]);
		if (this.isLastChild()) {
			//dojo.debug("Checked last node for "+this);
			//dojo.debug("Parent last is "+this.parent.children[this.parent.children.length-1]);
			//dojo.debug("last node => add isTreeLast for "+this);
			dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode) + ' '+this.tree.classPrefix+'IsLast')
		}
		//dojo.profile.end("viewAddLayout");
		//dojo.debug("viewAddLayout out");

	},


	viewRemoveLayout: function() {
		//dojo.debug("viewRemoveLayout in "+this);
		//dojo.profile.start("viewRemoveLayout");
		//dojo.debug((new Error()).stack);
		dojo.html.removeClass(this.domNode, this.tree.classPrefix+"IsRoot");
		dojo.html.removeClass(this.domNode, this.tree.classPrefix+"IsLast");
		//dojo.profile.end("viewRemoveLayout");
	},

	viewGetExpandClass: function() {
		if (this.isFolder) {
			return this.isExpanded ? "ExpandOpen" : "ExpandClosed";
		} else {
			return "ExpandLeaf";
		}
	},

	viewSetExpand: function() {
		//dojo.profile.start("viewSetExpand");

		//dojo.debug("viewSetExpand in "+this);

		var expand = this.tree.classPrefix+this.viewGetExpandClass();
		var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"Expand\\w+",'g');

		dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+expand);

		//dojo.debug(dojo.html.getClass(this.domNode))
		//dojo.profile.end("viewSetExpand");
		this.viewSetHasChildrenAndExpand();
	},

	viewGetChildrenClass: function() {
		return 'Children'+(this.children.length ? 'Yes' : 'No');
	},

	viewSetHasChildren: function() {
		//dojo.debug(this+' '+this.children.length)

		var clazz = this.tree.classPrefix+this.viewGetChildrenClass();

		var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"Children\\w+",'g');

		dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+clazz);

		this.viewSetHasChildrenAndExpand();
	},

	/**
	 * set TreeStateChildrenYes-ExpandClosed pair
	 * needed for IE, because IE reads only last class from .TreeChildrenYes.TreeExpandClosed pair
	 */
	viewSetHasChildrenAndExpand: function() {
		var clazz = this.tree.classPrefix+'State'+this.viewGetChildrenClass()+'-'+this.viewGetExpandClass();

		var reg = new RegExp("(^|\\s)"+this.tree.classPrefix+"State[\\w-]+",'g');

		dojo.html.setClass(this.domNode, dojo.html.getClass(this.domNode).replace(reg,'') + ' '+clazz);
	},

	viewUnfocus: function() {
		dojo.html.removeClass(this.labelNode, this.tree.classPrefix+"LabelFocused");
	},

	viewFocus: function() {
		dojo.html.addClass(this.labelNode, this.tree.classPrefix+"LabelFocused");
	},

    viewEmphasize: function() {
        dojo.html.clearSelection(this.labelNode);

		dojo.html.addClass(this.labelNode, this.tree.classPrefix+'NodeEmphasized');
    },

    viewUnemphasize: function() {
        dojo.html.removeClass(this.labelNode, this.tree.classPrefix+'NodeEmphasized');
    },


// ================================ detach from parent ===================================

	detach: function() {
		if (!this.parent) return;

		var parent = this.parent;
		var index = this.getParentIndex();

		this.doDetach.apply(this, arguments);

		dojo.event.topic.publish(this.tree.eventNames.afterDetach,
			{ child: this, parent: parent, index:index }
		);

	},


	/* node does not leave tree */
	doDetach: function() {
		//dojo.debug("doDetach in "+this+" parent "+this.parent+" class "+dojo.html.getClass(this.domNode));

		var parent = this.parent;

		//dojo.debug(parent.containerNode.style.display)

		if (!parent) return;

		var index = this.getParentIndex();


		this.viewRemoveLayout();

		dojo.widget.DomWidget.prototype.removeChild.call(parent, this);

		var siblingsCount = parent.children.length;

		//dojo.debug("siblingsCount "+siblingsCount);

		if (siblingsCount > 0) {
			if (index == 0) {	// deleted first node => update new first
				parent.children[0].viewUpdateLayout();
			}
			if (index == siblingsCount) { // deleted last node
				parent.children[siblingsCount-1].viewUpdateLayout();
			}
		} else {
			if (parent.isTreeNode) {
				parent.viewSetHasChildren();
			}
		}

		if (this.tree.unsetFolderOnEmpty && !parent.children.length && parent.isTreeNode) {
			parent.unsetFolder();
		}

		//dojo.debug(parent.containerNode.style.display)

		this.parent = null;
	},


	/**
	 * publish destruction event so that controller may unregister/unlisten
	 */
	destroy: function() {

		dojo.event.topic.publish(this.tree.eventNames.beforeNodeDestroy, { source: this } );

		this.detach();

		return dojo.widget.HtmlWidget.prototype.destroy.apply(this, arguments);
	},


	expand: function(){

		if (this.isExpanded) return;


		//dojo.profile.start("expand "+this);

		//dojo.debug("expand in "+this);

		//dojo.profile.start("expand - lazy init "+this);
		if (this.tryLazyInit) {
			this.setChildren();
			this.tryLazyInit = false;
		}

		//dojo.profile.end("expand - lazy init "+this);


		this.isExpanded = true;

		this.viewSetExpand();

		//dojo.profile.start("expand - showChildren "+this);

		/**
		 * no matter if I have children or not. need to show/hide container anyway.
		 * use case: empty folder is expanded => then child is added, container already shown all fine
		 */
		this.showChildren();

		//dojo.profile.end("expand - showChildren "+this);


		//dojo.profile.end("expand "+this);
	},


	collapse: function(){

		if (!this.isExpanded) return;

		this.isExpanded = false;

		this.hideChildren();
	},


	hideChildren: function(){
		this.tree.toggleObj.hide(
			this.containerNode, this.tree.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onHideChildren")
		);
	},


	showChildren: function(){
		//dojo.profile.start("showChildren"+this);

		this.tree.toggleObj.show(
			this.containerNode, this.tree.toggleDuration, this.explodeSrc, dojo.lang.hitch(this, "onShowChildren")
		);

		//dojo.profile.end("showChildren"+this);
	},



	onShowChildren: function() {

		//dojo.profile.start("onShowChildren"+this);

        this.onShow();

		//dojo.profile.end("onShowChildren"+this);

		dojo.event.topic.publish(this.tree.eventNames.afterExpand, {source: this} );
	},

	onHideChildren: function() {

		this.viewSetExpand();
		this.onHide();
		dojo.event.topic.publish(this.tree.eventNames.afterCollapse, {source: this} );
	},

	/* Edit current node : change properties and update contents */
	setTitle: function(title) {
		var oldTitle = this.title;

		this.labelNode.innerHTML = this.title = title;

		dojo.event.topic.publish(this.tree.eventNames.afterSetTitle, { source: this, oldTitle:oldTitle });

	},


	toString: function() {
		return '['+this.widgetType+', '+this.title+']';
	}


});
