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


dojo.require("dojo.event.*");
dojo.require("dojo.json")
dojo.require("dojo.io.*");
dojo.require("dojo.widget.TreeCommon");


/**
 * Iterates the tree processNext
 * filterFunc/filterObj called to determine if I need to pass the node
 *
 * callFunc/callObj called to process the node
 *    callObj.callFunc(elem, iterator) should call iterator.forward() to go on
 *    callFunc may change elem to another object (e.g create widget from it),
 *       keeping its parent and parent position are untouched *
 *
 * finishFunc/finishObj called at the end
 *
 * TODO: it should work only sync-way to solve CPU-hungry tasks
 */
 dojo.declare(
 	"dojo.widget.TreeTimeoutIterator",
 	null,

function(elem, callFunc, callObj) {
	var _this = this;

	this.currentParent = elem;

	this.callFunc = callFunc;
	this.callObj = callObj ? callObj: this;
	this.stack = [];
},

{
	// public
	maxStackDepth: Number.POSITIVE_INFINITY,

	stack: null,
	currentParent: null,

	currentIndex: 0,

	filterFunc: function() { return true },

	finishFunc: function() { return true },


	setFilter: function(func, obj) {
		this.filterFunc = func;
		this.filterObj = obj;
	},


	setMaxLevel: function(level) {
		this.maxStackDepth = level-2;
	},

	forward: function(timeout) {
		var _this = this;

		if (this.timeout) { // if timeout required between forwards
			// tid will be assigned at the end of outer func execution
			var tid = setTimeout(function() {_this.processNext(); clearTimeout(tid); }, _this.timeout);
		} else {
			return this.processNext();
		}
	},

	start: function(processFirst) {
		if (processFirst) {
			return this.callFunc.call(this.callObj, this.currentParent, this);
		}

		return this.processNext();
	},

	/**
	 * @private
	 * find next node, move current parent to it if possible & process
	 */
	processNext: function() {

		//dojo.debug("processNext with currentParent "+this.currentParent+" index "+this.currentIndex);
		var handler;

		var _this = this;

		var found;

		var next;

		if (this.maxStackDepth == -2) {
			return; // process only first cause level=0, do not process children
		}

		while (true) {
			var children = this.currentParent.children;

			if (children && children.length) {

				// look for a node that can be the next target
				do {
					next = children[this.currentIndex];
					//dojo.debug("check "+next);
				} while (this.currentIndex++ < children.length && !(found = this.filterFunc.call(this.filterObj,next)));


				if (found) {
					//dojo.debug("found "+next);
					// move to next node as new parent if depth is fine
					// I can't check current children to decide whether to move it or not,
					// because expand may populate children
					if (next.isFolder && this.stack.length <= this.maxStackDepth) {
						this.moveParent(next,0);
					}
					//dojo.debug("Run callFunc on "+next);
					return this.callFunc.call(this.callObj, next, this);
				}
			}

			if (this.stack.length) {
				this.popParent();
				continue;
			}

			break;
		}

		/**
		 * couldn't find next node to process, finish here
		 */
		return this.finishFunc.call(this.finishObj);

	},

	setFinish: function(func, obj) {
		this.finishFunc = func;
		this.finishObj = obj;
	},

	popParent: function() {
		var p = this.stack.pop();
		//dojo.debug("Pop "+p[0]+":"+p[1]);
		this.currentParent = p[0];
		this.currentIndex = p[1];
	},

	moveParent: function(nextParent, nextIndex) {
		//dojo.debug("Move from "+this.currentParent+":"+this.currentIndex+" to "+nextParent+":"+nextIndex);
		this.stack.push([this.currentParent, this.currentIndex]);
		this.currentParent = nextParent;
		this.currentIndex = nextIndex;
	}

});