
var INDEX_NONE = -1;

// External SOA data.
SheduleManager_services_name 	      = new Array;
SheduleManager_services_url 	      = new Array;
SheduleManager_services_methods       = new Array;

SheduleManager_task_green_mile 	      = new Array; // ;-)
SheduleManager_task_heap	      = new Array; // ...... many, many ......
SheduleManager_finder 		      = new Array; // Task map.

SheduleManager_stopped		      = false;

SheduleManager_info_task_id	      = INDEX_NONE;
SheduleManager_progress_flag	      = false;

SheduleManager_status_text	      = "";

SheduleManager_requests		      = 0;
SheduleManager_max_requests	      = 0;
SheduleManager_limit_request	      = 4;

// Task implementation.

var TF_NOTHING			      = 0;
var TF_FIRE_RUN 		      = 1;
var TF_STARTED			      = 2;
var TF_FINISHED			      = 4;
var TF_SLEEP			      = 8;
var TF_RUN_CYCLE		      = 16;
var TF_RUN_ONCE			      = 32;
var TF_PARAMS_IS_BORN		      = 64;
var TF_PARAMS_NO_BORN		      = 128;
var TF_AJAX_REQUEST_PROCESS	      = 256;
var TF_AJAX_REQUEST_SLEEP	      = 512;

var MAX_FLAG_VALUE		      = 1023;

Task.prototype.xmlHttp 		      = null;
Task.prototype.taskFlag 	      = TF_NOTHING;
Task.prototype.suId 		      = null;
Task.prototype.srv_url 		      = null;
Task.prototype.srv_method 	      = null;
Task.prototype.mtd_params 	      = null;
Task.prototype.async		      = false;
Task.prototype.callback 	      = null;
Task.prototype.userData		      = null;
Task.prototype.status_info	      = null;
Task.prototype.status_icon	      = null;
Task.prototype.total_request	      = 0;

Task.prototype.invoke = function() {

//	if(SheduleManager_requests >= SheduleManager_limit_request) {
//		return;
//	}

	if((this.taskFlag & TF_RUN_ONCE) && (this.taskFlag & TF_STARTED))
		return;
	if(this.taskFlag & TF_FINISHED)
		return;
	if(this.srv_url == null && this.srv_method == null)
		return;
	if(this.xmlHttp == null) {
		this.xmlHttp = SOAPClient._getXmlHttp();
		this.taskFlag |= TF_STARTED;
	}
	if(this.taskFlag & TF_PARAMS_IS_BORN || this.taskFlag & TF_PARAMS_NO_BORN) {
		this.taskFlag &= (MAX_FLAG_VALUE - TF_PARAMS_IS_BORN);
		SOAPClient.invoke(this.srv_url, this.srv_method, this.mtd_params, this.async, this.callback, this.xmlHttp);
		this.total_request++;

		this.taskFlag |= TF_AJAX_REQUEST_PROCESS;

		SheduleManager_requests++;
		SheduleManager_max_requests++;
	}
};

Task.prototype.setParams = function(mtd_params, async, callback) {
	this.mtd_params = mtd_params; 	this.async = async;
	this.callback = callback; 		this.taskFlag |= TF_PARAMS_IS_BORN;

	if(this.taskFlag & TF_FIRE_RUN) {
		this.invoke();
        }
};

Task.prototype.setStatusInfo = function(st_info, st_icon) {
	this.status_info = st_info; this.status_icon = st_icon;
	if(this.status_info != null)
		this.status_info += "<strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong>";
	SheduleManager_progress_flag = true;
};

// Task info.
Task.prototype.getName = function()		{ return this.srv_method; };
Task.prototype.getSignature = function() 	{ return this.srv_method + "$" + this.suId; };
Task.prototype.getStatus = function() 		{ return this.xmlHttp.readyState; };
Task.prototype.getUserData = function()		{ return this.userData; };

Task.prototype.setUserData = function(udata)	{ this.userData = udata; };

// Flag set/zero/check methods.
Task.prototype.setFlag = function(flag) 		{ this.taskFlag |= flag; };
Task.prototype.zeroFlag = function(flag) 		{ this.taskFlag &= (MAX_FLAG_VALUE - flag); };
Task.prototype.checkFlag = function(flag) 		{ return (this.taskFlag & flag); };
Task.prototype.swapFlag = function(old_flag, new_flag)	{ this.zeroFlag(old_flag); this.setFlag(new_flag); };

//function Task() {}
//function Task(srv_url, srv_method, flag) { this.srv_url = srv_url; this.srv_method = srv_method; this.taskFlag = flag; }

function Task(srv_name, srv_method, flag) { 
	this.srv_url = SheduleManager_services_url[srv_name + ""];
	this.srv_method = srv_method;
	this.taskFlag = flag;
	//alert(this.taskFlag);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Task manager.

SheduleManager.stopped = false;

// Static methods.
SheduleManager.add_service = function(name, url) {
	SheduleManager_services_name.push(name);
	SheduleManager_services_url[name + ""] = url;
	SheduleManager_services_methods[name + ""] = new Array;
};

SheduleManager.add_methods = function(srv_name, srv_method) { SheduleManager_services_methods[srv_name + ""].push(srv_method); };

SheduleManager.get_service = function(name) { return SheduleManager_services_url[name + ""]; };

SheduleManager.add_task = function(srv_name, srv_method, flag) {
	SheduleCycle.stopped = true;
        flag |= TF_AJAX_REQUEST_SLEEP;
	var task = new Task(srv_name, srv_method, flag);
	task.suId = 0;
	SheduleManager_finder[task.getSignature() + ""] = SheduleManager_task_green_mile.length;
	SheduleManager_task_green_mile.push(task);
	SheduleCycle.stopped = false;
	//alert("add_task " + task.taskFlag);
	return task;
};

SheduleManager.getLastTaskWithStatusInfo = function() {
	var lastTask;

	if(SheduleManager_task_green_mile.length == 0) {
		return INDEX_NONE;
	}

	for(var i=SheduleManager_task_green_mile.length-1; i>=0; i--) {
		lastTask = SheduleManager_task_green_mile[i];
		if(lastTask.status_icon != null || lastTask.status_info != null)
			return i;
	}
	return INDEX_NONE;
};

SheduleManager.buildFlagString = function(flag) {
/********************************
var TF_NOTHING		= 0;
var TF_FIRE_RUN 	= 1;
var TF_STARTED		= 2;
var TF_FINISHED		= 4;
var TF_SLEEP		= 8;
var TF_RUN_CYCLE	= 16;
var TF_RUN_ONCE		= 32;
var TF_PARAMS_IS_BORN	= 64;
var TF_PARAMS_NO_BORN	= 128;
********************************/
	var flagSep = "";
	var flagString = "{ "; 
	if(flag & TF_NOTHING) { flagString += flagSep + "TF_NOTHING"; flagSep += " | "; }
	if(flag & TF_FIRE_RUN) { flagString += flagSep + "TF_FIRE_RUN"; flagSep += " | "; }
	if(flag & TF_STARTED) { flagString += flagSep + "TF_STARTED"; flagSep += " | "; }
	if(flag & TF_FINISHED) { flagString += flagSep + "TF_FINISHED"; flagSep += " | "; }
	if(flag & TF_SLEEP) { flagString += flagSep + "TF_SLEEP"; flagSep += " | "; }
	if(flag & TF_RUN_CYCLE) { flagString += flagSep + "TF_RUN_CYCLE"; flagSep += " | "; }
	if(flag & TF_RUN_ONCE) { flagString += flagSep + "TF_RUN_ONCE"; flagSep += " | "; }
	if(flag & TF_PARAMS_IS_BORN) { flagString += flagSep + "TF_PARAMS_IS_BORN"; flagSep += " | "; }
	if(flag & TF_PARAMS_NO_BORN) { flagString += flagSep + "TF_PARAMS_NO_BORN"; flagSep += " | "; }
	flagString += " }";

	return flagString;
};

SheduleManager.getLastTaskInfo = function() {
	if(SheduleManager_task_green_mile.length == 0)
		return "";
	var task = SheduleManager_task_green_mile[SheduleManager_task_green_mile.length-1];
	return "   METHOD: " + task.srv_method + " (*) TASK_FLAGS = " + SheduleManager.buildFlagString(task.taskFlag) + "     ";
};

SheduleManager.isHaveFireTask = function() {
	var fireTask;
	if(SheduleManager_task_green_mile.length == 0) {
		return false;
	}
	for(var i=0; i<SheduleManager_task_green_mile.length; i++) {
		fireTask = SheduleManager_task_green_mile[i];
		if(fireTask.taskFlag & TF_FIRE_RUN)
			return true;
	}
	return false;
};

SheduleManager.process = function() {
	var currTask, infoTask;

	if(SheduleManager_progress_flag) {
		lit = SheduleManager.getLastTaskWithStatusInfo();
		if(lit != INDEX_NONE) {
			infoTask = SheduleManager_task_green_mile[lit];
			//status_bar.setIconPosition("right");
			//status_bar.setLabel(" 8-) " + infoTask.status_info);
			//status_bar.setIcon(infoTask.status_icon);
		} else {
			//status_bar.setIconPosition("left");
			//status_bar.setLabel(" :-)");
			//status_bar.setIcon("icon/16/connect-established.png");
		}
		SheduleManager_progress_flag = false;
	}

	for(var i=0; i<SheduleManager_task_green_mile.length; i++) {
		currTask = SheduleManager_task_green_mile[i];

		//debug_window.debug("Total tasks: " + SheduleManager_task_green_mile.length + "  :  Total requests: " + SheduleManager_requests + "  :  MAX_REQ: " + SheduleManager_requests);

		if(currTask.checkFlag(TF_STARTED)) {
			if(currTask.checkFlag(TF_RUN_ONCE)) {
				if(currTask.checkFlag(TF_AJAX_REQUEST_PROCESS)) {
					if(currTask.getStatus() == 4) { // Non-full terminate. Callback is work.
						currTask.swapFlag(TF_AJAX_REQUEST_PROCESS, TF_AJAX_REQUEST_SLEEP);
						currTask.swapFlag(TF_STARTED, TF_FINISHED);
						SheduleManager_requests--;
					}
				}
			}
			if(currTask.checkFlag(TF_RUN_CYCLE)) {
				if(currTask.checkFlag(TF_AJAX_REQUEST_PROCESS)) {
					if(currTask.getStatus() == 4) {  // Non-full terminate. Callback is work.
						currTask.swapFlag(TF_AJAX_REQUEST_PROCESS, TF_AJAX_REQUEST_SLEEP);
						SheduleManager_requests--;
					}
				}
			}
		}

		if(currTask.checkFlag(TF_FINISHED)) {
			SheduleManager_finder[currTask.getSignature() + ""] = INDEX_NONE;
			SheduleManager_task_green_mile.splice(i, 1); // Remove task.
			SheduleManager_progress_flag = true;
			continue; // Next task.
		}

		if(!(currTask.taskFlag & TF_FIRE_RUN))
			currTask.invoke();
	}
};

function SheduleManager() {}

function SheduleCycle() {
	if(!SheduleManager_stopped)
		SheduleManager.process();
	setTimeout("SheduleCycle()", 1000);
}

