/**
* GF()
* 
* Groups elemetary methods that are used widely in the whole GexoFramework.
* The class mainly consists of static methods availble to call from
* any place in the application.
*/
function GF() {};

/**
* const GF.NULL - Null equivalent.
*/
GF.NULL = -9999;

/**
* GF.ExtendClass(sType, fChild[, oChildStatic])
* 
* Function that realises the classical inheritance model.
* 
* Treats the current class as the base class and extends it with the one
* passed as the second argument. The first argument specifies the child
* class' name. The third argument, if defined, is an object consisting
* of the child class' static members.
* 
* @return function - New class implementing both source classes.
* @param sType string - Name of the new class.
* @param fChild function - The definition of the derived class.
* @param fChildStatic object - An object consisting of the child class'
*  static members. It should be built of name-definition pairs.
* @param bNoBaseConstructor bool - If set to true, the base class'
*  constructor isn't invoked when derived object is created.
*/
GF.ExtendClass = function(sType, fChild, oChildStatic, bNoBaseConstructor) {
	var fBase = this;
	var fExtended = function() {
		var aBaseArguments = [sType];
		for (var i = 0; i < arguments.length; i++) {
			aBaseArguments.push(arguments[i]);
		}
		if (bNoBaseConstructor != undefined && bNoBaseConstructor) {
			return fChild.apply(this, arguments);
		}
		var result = fBase.apply(this, aBaseArguments);
		if (result === false) {
			return result;
		}
		return fChild.apply(this, arguments);
	};
	fExtended.GF_ImplementMembers(fBase.prototype);
	fExtended.GF_ImplementStaticMembers(fBase, sType);
	fExtended.GF_ImplementStaticMembers(oChildStatic);
	return fExtended;
};

/**
* GF.ImplementMembers(oProto)
* 
* Implements all the proto members as the current class' member functions.
* 
* @param oProto object - An object consisting of the class' methods.
*/
GF.ImplementMembers = function(oProto) {
  for(var i in oProto) {
		this.prototype[i] = oProto[i];
	}
};

/**
* GF.ImplementStaticMembers(oProto, sType)
* 
* Implements all the proto members as the current class' static members.
* 
* The function is prepared to cope with the GetInstance-like methods of GF_Instance
* class. It overrides the standard argument list so that the second argument
* is always the calling class' name.
* 
* @param oProto object - An object consisting of the class' static members.
* @param sType string - Name of the derived class.
*/
GF.ImplementStaticMembers = function(oProto, sType) {
	for(var i in oProto) {
		if (i == 'GetInstance') {
			this[i] = function(oNode) {
				return GF_Instance.GetInstance(oNode, sType);
			}
		}
		else if (i == 'GetCurrentInstance') {
			this[i] = function(oNode) {
				return GF_Instance.GetCurrentInstance(oNode, sType);
			}
		}
		else {
			this[i] = oProto[i];
		}
	}
};

/**
* GF.NewConstructor(fConstructor)
* 
* Prepares a safe constructor that catches all the thrown exceptions during
* its evaluation. It is recommended that all newly created constructors should
* be processed using this method. Otherwise you should manually ensure to 
* correctly apply exception catching.
* 
* @return function - Safe object constructor.
* @param fConstructor function - A function pointer to the base constructor.
*/
GF.NewConstructor = function(fConstructor) {
	var fSafeConstructor = function(jTarget, oOptions) {
		try {
			return fConstructor.apply(this, arguments);
		}
		catch (xException) {
			GF_Debug.HandleException(xException);
			this.RemoveInstance();
			return false;
		}
	};
	return fSafeConstructor;
};

/**
* GF.NewEventHandler(fHandler)
* 
* Prepares a safe event handler that catches all the thrown exceptions. It is
* recommended that all newly created event handlers should be processed using
* this method. Otherwise you should manually ensure to correctly apply
* exception catching.
* 
* @return function - Safe event handler.
* @param fHandler function - A function pointer to the base event handler.
*/
GF.NewEventHandler = function(fHandler) {
	var fSafeHandler = function(eEvent) {
		try {
			return fHandler.apply(this, arguments);
		}
		catch (xException) {
			GF_Debug.HandleException(xException);
			return false;
		}
	};
	return fSafeHandler;
};

/**
* GF.NewSafeMethod(fMethod)
* 
* Prepares a safe method that catches all the thrown exceptions. It is
* recommended that all newly created methods that can be invoked externally
* should be processed using this method. Otherwise you should manually 
* ensure to correctly apply exception catching.
* 
* @return function - Safe method.
* @param fHandler function - A function pointer to the base method.
*/
GF.NewSafeMethod = function(fMethod) {
	var fSafeHandler = function(eEvent) {
		try {
			return fMethod.apply(this, arguments);
		}
		catch (xException) {
			GF_Debug.HandleException(xException);
			return false;
		}
	};
	return fSafeHandler;
};

/**
* GF.GetClasses(jNode)
* 
* Returns an array of the node's classes.
* 
* @return array - Classname array.
* @param jNode jQuery - Target DOM node.
*/
GF.GetClasses = function(jNode) {
	return jNode.attr('class').split(' ');
};

/**
* GF.GetChunkFromClass(jNode, sNeedle)
* 
* Looks int he node's class string for a chunk that starts with sNeedle.
* When found, returns the remaining part of such chunk.
* 
* @return string - Remaining part of the found chunk or an empty string.
* @param jNode jQuery - Node which classes are subject to search.
* @param sNeedle string - Beginning of the chunk that we want to find.
*/
GF.GetChunkFromClass = function(jNode, sNeedle) {
	var aClasses = GF.GetClasses(jNode);
	for (var i in aClasses) {
		if (aClasses[i].substr(0, sNeedle.length) == sNeedle) {
			return aClasses[i].substr(sNeedle.length);
		}
	}
	GF_Debug.Warning('Desired string (' + sNeedle + ') was not found in any of the node\'s classes (class string: "' + jNode.attr('class') + '").');
	return '';
};

/**
* GF.GetIdFromFieldName(sFieldName)
* 
* Extracts the field's id from its name. It's used to process and identify fields
* that names are in an array-form, e.g. "fieldName[123]". The function returns "123"
* in such case. It's safe to use it with multi dimensional arrays - only the last
* id will be returned.
* 
* @return string - Element's id.
* @param sFieldName string - The field's name from which the id needs to be extracted.
*/
GF.GetIdFromFieldName = function(sFieldName) {
	var aIds = sFieldName.match(/\[[^\]]+\]/g);
	var sLastId = aIds.pop();
	return sLastId.substr(1, sLastId.length - 2);
};

/**
* GF.CheckboxesCheck(jContext)
* 
* Checks all the descendant checkboxes of the jContext node.
* 
* @param jContext jQuery - Predecessor of the checkboxes to check.
*/
GF.CheckboxesCheck = function(jContext) {
	jContext.checkCheckboxes();
};

/**
* GF.CheckboxesUncheck(jContext)
* 
* Unchecks all the descendant checkboxes of the jContext node.
* 
* @param jContext jQuery - Predecessor of the checkboxes to uncheck.
*/
GF.CheckboxesUncheck = function(jContext) {
	jContext.unCheckCheckboxes();
};

/**
* GF.StopPropagation(eEvent)
* 
* A generic event handler that stops the event propagation.
* 
* @param eEvent EventObject - jQuery's event object.
*/
GF.StopPropagation = function(eEvent) {
	eEvent.stopImmediatePropagation();
	eEvent.stopPropagation();
	return true;
};

/**
* GF.PreventDefault(eEvent)
* 
* A generic event handler that prevents the browser from invoking default action.
* 
* @param eEvent EventObject - jQuery's event object.
*/
GF.PreventDefault = function(eEvent) {
	eEvent.preventDefault();
	return true;
};

/**
* GF.InArray(aArray, mValue)
* 
* Checks whether the mValue element exists in the aArray.
* 
* @return bool - True if the value exists in array or false if not.
* @param aArray array - Array of values.
* @param mValue mixed - Value that we want to find.
*/
GF.InArray = function(aArray, mValue) {
	for (var i in aArray) {
		if (aArray[i] == mValue) {
			return true;
		}
	}
	return false;
};

/**
* GF.DeleteFromArray(aArray, mValue)
* 
* Deletes safely the mValue from aArray.
* 
* @return array - The modified array.
* @param aArray array - Array of values.
* @param mValue mixed - Value that we want to delete.
*/
GF.DeleteFromArray = function(aArray, mValue) {
	while(true) {
		var n = aArray.length;
		var j = 0;
		for (var i in aArray) {
			if (aArray[i] == mValue) {
				aArray.splice(i, 1);
			}
			j++;
		}
		if (j == n) {
			break;
		}
	}
	return aArray;
};

/**
* GF.DeleteFromArrayAt(aArray, mIndex)
* 
* Deletes safely the mIndex element from aArray.
* 
* @return array - The modified array.
* @param aArray array - Array of values.
* @param mIndex mixed - Index of element that we want to delete.
*/
GF.DeleteFromArrayAt = function(aArray, mIndex) {
	while(true) {
		var n = aArray.length;
		var j = 0;
		for (var i in aArray) {
			if (i == mIndex) {
				aArray.splice(i, 1);
			}
			j++;
		}
		if (j == n) {
			break;
		}
	}
	return aArray;
};

GF.Clone = function(mSource) {
	if (mSource == null || typeof(mSource) != 'object') {
		return mSource;
	}
	var mTemp = new mSource.constructor();
	for (var sKey in mSource) {
		mTemp[sKey] = GF.Clone(mSource[sKey]);
	}
	return mTemp;
};

/**
* GF.CountMembers(oObject)
* 
* Counts the enumerable members of oObject.
* 
* @return int - Number of members.
* @param oObject Object - Object which members we want to count.
*/
GF.CountMembers = function(oObject) {
	var iCount = 0;
	for (var i in oObject) {
		iCount++;
	}
	return iCount;
};

/* Function prototype extensions */

Function.prototype.GF_Extend = GF.ExtendClass;
Function.prototype.GF_ImplementMembers = GF.ImplementMembers;
Function.prototype.GF_ImplementStaticMembers = GF.ImplementStaticMembers;

