/*
	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.TreeLoadingControllerV3");

dojo.require("dojo.widget.TreeBasicControllerV3");
dojo.require("dojo.event.*");
dojo.require("dojo.json")
dojo.require("dojo.io.*");
dojo.require("dojo.Deferred");
dojo.require("dojo.DeferredList");

dojo.declare(
	"dojo.Error",
	Error,
	function(message, extra) {
		this.message = message;
		this.extra = extra;
		this.stack = (new Error()).stack;
	}
);

dojo.declare(
	"dojo.CommunicationError",
	dojo.Error,
	function() {
		this.name="CommunicationError";
	}
);

dojo.declare(
	"dojo.LockedError",
	dojo.Error,
	function() {
		this.name="LockedError";
	}
);

dojo.declare(
	"dojo.FormatError",
	dojo.Error,
	function() {
		this.name="FormatError";
	}
);

dojo.declare(
	"dojo.RpcError",
	dojo.Error,
	function() {
		this.name="RpcError";
	}
);

dojo.widget.defineWidget(
	"dojo.widget.TreeLoadingControllerV3",
	dojo.widget.TreeBasicControllerV3,
{
	RpcUrl: "",

	RpcActionParam: "action", // used for GET for RpcUrl

	preventCache: true,

	checkValidRpcResponse: function(type, obj) {
		if (type != "load") {
			var extra = {}
			for(var i=1; i<arguments.length;i++) {
				dojo.lang.mixin(extra, arguments[i]);
			}
			return new dojo.CommunicationError(obj, extra);
		}

		if (typeof obj != 'object') {
			return new dojo.FormatError("Wrong server answer format "+(obj && obj.toSource ? obj.toSource() : obj)+" type "+(typeof obj), obj);
		}

		//dojo.debugShallow(obj);

		if (!dojo.lang.isUndefined(obj.error)) {
			return new dojo.RpcError(obj.error, obj);
		}

		return false;
	},


	getDeferredBindHandler: function(/* dojo.rpc.Deferred */ deferred){
		// summary
		// create callback that calls the Deferred's callback method

		return dojo.lang.hitch(this,
			function(type, obj){
				//dojo.debug("getDeferredBindHandler "+obj.toSource());

				var error = this.checkValidRpcResponse.apply(this, arguments);

				if (error) {
					deferred.errback(error);
					return;
				}

				deferred.callback(obj);
			}
		);

	},

	getRpcUrl: function(action) {

		// RpcUrl=local meant SOLELY for DEMO and LOCAL TESTS
		if (this.RpcUrl == "local") {
			var dir = document.location.href.substr(0, document.location.href.lastIndexOf('/'));
			var localUrl = dir+"/local/"+action;
			//dojo.debug(localUrl);
			return localUrl;
		}

		if (!this.RpcUrl) {
			dojo.raise("Empty RpcUrl: can't load");
		}

		var url = this.RpcUrl;

		if (url.indexOf("/") != 0) { // not absolute
			var protocol = document.location.href.replace(/:\/\/.*/,'');
			var prefix = document.location.href.substring(protocol.length+3);

			if (prefix.lastIndexOf("/") != prefix.length-1) {
				prefix = prefix.replace(/\/[^\/]+$/,'/'); // strip file name
			}
			if (prefix.lastIndexOf("/") != prefix.length-1) {
				prefix = prefix+'/'; // add / if not exists it all
			}
			//dojo.debug(url);
			url = protocol + '://' + prefix + url;
		}


		return url + (url.indexOf("?")>-1 ? "&" : "?") + this.RpcActionParam+"="+action;
	},


	/**
	 * Add all loaded nodes from array obj as node children and expand it
	*/
	loadProcessResponse: function(node, result) {
		//dojo.debug("Process response "+node);

		if (!dojo.lang.isArray(result)) {
			throw new dojo.FormatError('loadProcessResponse: Not array loaded: '+result);
		}

		node.setChildren(result);

	},

	/**
	 * kw = { url, sync, params }
	 */
	runRpc: function(kw) {
		var _this = this;

		var deferred = new dojo.Deferred();

		dojo.io.bind({
			url: kw.url,
			handle: this.getDeferredBindHandler(deferred),
			mimetype: "text/javascript",
			preventCache: this.preventCache,
			sync: kw.sync,
			content: { data: dojo.json.serialize(kw.params) }
		});

		return deferred;

	},



	/**
	 * Load children of the node from server
	 * Synchroneous loading doesn't break control flow
	 * I need sync mode for DnD
	*/
	loadRemote: function(node, sync){
		var _this = this;

		var params = {
			node: this.getInfo(node),
			tree: this.getInfo(node.tree)
		};


		var deferred = this.runRpc({
			url: this.getRpcUrl('getChildren'),
			sync: sync,
			params: params
		});

		deferred.addCallback(function(res) { return _this.loadProcessResponse(node,res) });



		return deferred;

	},

	batchExpandTimeout: 0,

	recurseToLevel: function(widget, level, callFunc, callObj, skipFirst, sync) {
		if (level == 0) return;



		if (!skipFirst) {
			var deferred = callFunc.call(callObj, widget, sync);
		} else {
			var deferred = dojo.Deferred.prototype.makeCalled();
		}

		//dojo.debug("expand deferred saved "+node+" sync "+sync);


		var _this = this;

		var recurseOnExpand = function() {
			var children = widget.children;
			var deferreds = [];
			for(var i=0; i<children.length; i++) {
				//dojo.debug("push recursive call for "+node.children[i]+" level "+level);
				deferreds.push(_this.recurseToLevel(children[i], level-1, callFunc, callObj, sync));
			}
			return new dojo.DeferredList(deferreds);
		}

		deferred.addCallback(recurseOnExpand);

		return deferred;
	},


	expandToLevel: function(nodeOrTree, level, sync) {
		return this.recurseToLevel(nodeOrTree, nodeOrTree.isTree ? level+1 : level, this.expand, this, nodeOrTree.isTree, sync);
	},

	loadToLevel: function(nodeOrTree, level, sync) {
		return this.recurseToLevel(nodeOrTree, nodeOrTree.isTree ? level+1 : level, this.loadIfNeeded, this, nodeOrTree.isTree, sync);
	},


	loadAll: function(nodeOrTree, sync) {
		return this.loadToLevel(nodeOrTree, Number.POSITIVE_INFINITY, sync);
	},



	expand: function(node, sync) {
		// widget which children are data objects, is UNCHECKED, but has children and shouldn't be loaded
		// so I put children check here too

		var _this = this;

		var deferred = this.startProcessing(node);

		deferred.addCallback(function() {
			return _this.loadIfNeeded(node, sync);
		});

		deferred.addCallback(function(res) {
			//dojo.debug("Activated callback dojo.widget.TreeBasicControllerV3.prototype.expand(node); "+res);
			dojo.widget.TreeBasicControllerV3.prototype.expand(node);
			return res;
		});

		deferred.addBoth(function(res) {
			_this.finishProcessing(node);
			return res;
		});



		return deferred;
	},


	loadIfNeeded: function(node, sync) {
		var deferred
		if (node.state == node.loadStates.UNCHECKED && node.isFolder && !node.children.length) {
			// populate deferred with other things to pre-do
			deferred = this.loadRemote(node, sync);
		} else {
			/* "fake action" here */
			deferred = new dojo.Deferred();
			deferred.callback();
		}

		return deferred;
	},

	/**
	 * 1) if specified, run check, return false if failed
	 * 2) if specified, run prepare
	 * 3) run make if prepare if no errors
	 * 4) run finalize no matter what happened, pass through make result
	 * 5) if specified, run expose if no errors
	 */
	runStages: function(check, prepare, make, finalize, expose, args) {
		var _this = this;

		if (check && !check.apply(this, args)) {
			return false;
		}

		var deferred = dojo.Deferred.prototype.makeCalled();


		if (prepare) {
			deferred.addCallback(function() {
				return prepare.apply(_this, args);
			});
		}


		//deferred.addCallback(function(res) { dojo.debug("Prepare fired "+res); return res});

		if (make) {
			deferred.addCallback(function() {
			var res = make.apply(_this, args);
			//res.addBoth(function(r) {dojo.debugShallow(r); return r;});
			return res;
			});
		}

		//deferred.addCallback(function(res) { dojo.debug("Main fired "+res); return res});

		if (finalize) {
			deferred.addBoth(function(res) {
				finalize.apply(_this, args);
				return res;
			});
		}


		// exposer does not affect result
		if (expose) {
			deferred.addCallback(function(res) {
				expose.apply(_this, args);
				return res;
			});
		}

		return deferred;
	},

	startProcessing: function(nodesArray) {
		var deferred = new dojo.Deferred();


		var nodes = dojo.lang.isArray(nodesArray) ? nodesArray : arguments;

		/*
		for(var i=0;i<nodes.length;i++) {
			dojo.debug(nodes[i]);
		}*/

		for(var i=0;i<nodes.length;i++) {
			if (nodes[i].isLocked()) {
				deferred.errback(new dojo.LockedError("item locked "+nodes[i], nodes[i]));
				//dojo.debug("startProcessing errback "+arguments[i]);
				return deferred;
			}
			if (nodes[i].isTreeNode) {
				//dojo.debug("mark "+nodes[i]);
				nodes[i].markProcessing();
			}
			nodes[i].lock();
		}

		//dojo.debug("startProcessing callback");

		deferred.callback();

		return deferred;
	},

	finishProcessing: function(nodesArray) {

		var nodes = dojo.lang.isArray(nodesArray) ? nodesArray : arguments;

		for(var i=0;i<nodes.length;i++) {
			if (!nodes[i].hasLock()) {
				// is not processed. probably we locked it and then met bad node in startProcessing
				continue;
			}
			//dojo.debug("has lock");
			nodes[i].unlock();
			if (nodes[i].isTreeNode) {
				//dojo.debug("unmark "+nodes[i]);
				nodes[i].unmarkProcessing();
			}
		}
	},

	// ----------------- refresh -----------------

	refreshChildren: function(nodeOrTree, sync) {
		return this.runStages(null, this.prepareRefreshChildren, this.doRefreshChildren, this.finalizeRefreshChildren, this.exposeRefreshChildren, arguments);
	},


	prepareRefreshChildren: function(nodeOrTree, sync) {
		var deferred = this.startProcessing(nodeOrTree);
		nodeOrTree.destroyChildren();

		nodeOrTree.state = nodeOrTree.loadStates.UNCHECKED;

		return deferred;
	},

	doRefreshChildren: function(nodeOrTree, sync) {
		return this.loadRemote(nodeOrTree, sync);
	},

	finalizeRefreshChildren: function(nodeOrTree, sync) {
		this.finishProcessing(nodeOrTree);
	},

	exposeRefreshChildren: function(nodeOrTree, sync) {
		nodeOrTree.expand();
	},

	// ----------------- move -----------------

	move: function(child, newParent, index/*,...*/) {
		return this.runStages(this.canMove, this.prepareMove, this.doMove, this.finalizeMove, this.exposeMove, arguments);
	},

	doMove: function(child, newParent, index) {
		//dojo.debug("MOVE "+child);
		child.tree.move(child, newParent, index);

		return true;
	},


	prepareMove: function(child, newParent, index, sync) {
		var deferred = this.startProcessing(newParent);
		deferred.addCallback(dojo.lang.hitch(this, function() {
			return this.loadIfNeeded(newParent, sync);
		}));
		return deferred;
	},

	finalizeMove: function(child, newParent) {
		this.finishProcessing(newParent);
	},

	// -------------------- createChild ------------

	prepareCreateChild: function(parent, index, data, sync) {
		var deferred = this.startProcessing(parent);

		deferred.addCallback(dojo.lang.hitch(this, function() {
			return this.loadIfNeeded(parent, sync);
		}));
		return deferred;
	},

	finalizeCreateChild: function(parent) {
		this.finishProcessing(parent);
	},

	// ---------------- clone ---------------

	prepareClone: function(child, newParent, index, deep, sync) {
		var deferred = this.startProcessing(child, newParent);
		deferred.addCallback(dojo.lang.hitch(this, function() {
			return this.loadIfNeeded(newParent, sync);
		}));
		return deferred;
	},

	finalizeClone: function(child, newParent) {
		this.finishProcessing(child, newParent);
	}

});
