/*
 * Controls class
 * - used by the Control class to store globally available objects
 * - defines an internal random "key" to be used by any control to determine if a new object wass added to the page or not.
 *
 * */
function _Controls(){// constructor for the main class
	this.controlList=new Array();
	this.idGenerator=0;
	this.globalVars={};
	this.globalFuncs={};

	this.generationKey=Math.random();
}

// updates the random key (generationKey)
_Controls.prototype.updateKey=function (){
	this.generationKey=Math.random()*this.idGenerator+(Math.random()/this.idGenerator);
}

// returns a cleaned-up list of elements
_Controls.prototype.getElements=function (){
	var ret=new Array();

	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			ret.push(this.controlList[i]);
		}
	}

	return ret;
}

// scan controls for specified attributes. returns a list of elements
_Controls.prototype.searchElements=function (attributes){
	var ret=new Array();
	if(attributes==null)attributes={};

	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var control=this.controlList[i];
			var child=control.child;

			var matched=true;

			for(var attr in attributes){
				if(!Object.isFunction(attributes[attr])){
					if(child.attributes[attr]!=attributes[attr]){
						matched=false;
						break;
					}
				}
			}

			if(matched){
				ret.push(control);
			}
		}
	}

	return ret;
}


// scan parent controls for specified attributes. returns a list of elements
_Controls.prototype.searchParentElements=function (attributes){
	var ret=new Array();
	if(attributes==null)attributes={};

	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var control=this.controlList[i];

			var matched=true;

			for(var attr in attributes){
				if(!Object.isFunction(attributes[attr])){
					if(control.attributes[attr]!=attributes[attr]){
						matched=false;
						break;
					}
				}
			}

			if(matched){
				ret.push(control);
			}
		}
	}

	return ret;
}


// scan controls for requested object
_Controls.prototype.searchElementsByType=function (objectType){
	var ret=new Array();

	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var control=this.controlList[i];
			var child=control.child;

			if(child.name==objectType){
				ret.push(control);
			}
		}
	}

	return ret;
}

// search the list of controls by using its DOM ID (i'm using .identify() from prototype)
_Controls.prototype.getControlByID=function (ID){
	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var childId;
			var control;

			control=this.controlList[i];

			child=control.child.preview;
			if($(child).identify()==ID){
				// call the inner remove() function with the given param
				return control;
			}
		}
	}
	return false;
}

// adds a new control to the global list (controlList)
_Controls.prototype.add=function (control){
	this.idGenerator++;
	this.controlList[this.idGenerator]=control;
	control._controlsID=this.idGenerator;

	this.updateKey();
}

// removes a control from the global list using the DOM id.
_Controls.prototype.removeByID=function (ID){
	Controls.setGlobal('pageChanged',2);
	$('button_fastSaveDocument').setStyle({'fontWeight':'bold'});

	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var childId;
			var control;

			control=this.controlList[i];

			child=control.child.preview;
			if($(child).identify()==ID){
				// call the inner remove() function with the given param
				this.remove(control);
				return true;
			}
		}
	}
	return false;
}

// removes a control from the global list using the DOM id.
_Controls.prototype.cloneById=function (ID){
	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i] && !Object.isFunction(this.controlList[i])){
			var childId;
			var control;

			control=this.controlList[i];

			child=control.child.preview;
			if($(child).identify()==ID){
				return this.clone(control);
			}
		}
	}
	return false;
}

// removes a control from the global list using the DOM id.
_Controls.prototype.clone=function (control){
	if(control){
		var child=control.child.preview;

		if(child){
			// try to make a clone of that object!
			var type=String(control.child.name).replace('_control_','');
			var newControl=new Control(type,control.child.attributes);
			control.clearFocus();
			newControl.setFocus();
			return newControl;
		}
	}

	return false;
}


// removes a control from the global list
_Controls.prototype.remove=function (control){
	var id=control._controlsID;

	control.destroy();

	this.controlList[id]=null;

	this.updateKey();

	refreshObjects();
}

// destroys all contained objects
_Controls.prototype.destroy=function (control){
	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i]){
			this.remove(this.controlList[i]);

			this.controlList[i]=null;
		}
	}

	this.globalVars=null;
	this.controlList=null;
}

// globally sets a function call.
_Controls.prototype.setGlobalCall=function (eventStr,functionCall,functionParams){
	if(functionParams==null)functionParams={};

	if(functionParams.oneShot==null)functionParams.oneShot=true;

	if(this.globalFuncs[eventStr]==null)this.globalFuncs[eventStr]=new Array();

	this.globalFuncs[eventStr].push({func:functionCall, oneShot:functionParams. oneShot,calls:0});
}

// globally calls functions set for a certain event
_Controls.prototype.globalCall=function (eventStr,functionParams){
	if(this.globalFuncs[eventStr]==null)this.globalFuncs[eventStr]=new Array();

	for(var i=0; i<this.globalFuncs[eventStr].length;i++){
		if(this.globalFuncs[eventStr][i]){
			this.globalFuncs[eventStr][i].func(functionParams);

			// if the function call was marked as "one-shot" then remove the function after this call
			if(this.globalFuncs[eventStr][i].oneShot){
				this.globalFuncs[eventStr][i]=null;
			}
		}
	}
}



// globally sets a variable.
_Controls.prototype.setGlobal=function (variable,value){
	this.globalVars[variable]=value;
}

// returns a global variable.
_Controls.prototype.getGlobal=function (variable){
	return this.globalVars[variable];
}

_Controls.prototype.expensiveFunctionCalled=function (attributes){
	if(isNaN(this.globalVars['expensiveCalls']))this.globalVars['expensiveCalls']=0;
	this.globalVars['expensiveCalls']++;
}

_Controls.prototype.isIdle=function (){
	var total=0;
	var idle=0;
	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i]){
			total++;
			if(this.controlList[i].status().status=='idle'){
				idle++;
			}
		}
	}

	if(idle == total){
		updatePageStatus({text:'idle',status:'idle'});

		if(this.getGlobal('onIdle')){
			var idleFcn=this.getGlobal('onIdle');
			idleFcn();
			this.setGlobal('onIdle',null);
		}
	}

	return idle/total;
}

_Controls.prototype.dispatchEvent=function (event,params){
	for(var i=0;i<this.controlList.length;i++){
		if(this.controlList[i]){
			if(this.controlList[i][event]){
				this.controlList[i][event](params);
			}
		}
	}
}

var Controls=new _Controls();
