/*
Author:	 Effie Nadiv
Version: 0.11.1
Date:	 15 Dec 2006
*/

/**
 * The Webforms Manager provides a form validation system
 * @ class
 */

MIXAM.util.Webforms = function(){
	var forms = document.forms,
		validatorsClassNames = "|requiredfieldvalidator|regularexpressionvalidator|comparevalidator|" +
			"customvalidator|rangevalidator|requiredpairvalidator|";

	var onFormSubmit = function(e){
		e = e || event;
		var form = $E.getTarget(e),
			elements,
			errorCount = 0,
			validator,
			i, j,
			firstEraticInput,
			panel;

        if (form.tagName != "FORM"){
            // target might be an input!
            form = form.form;
        }

        // remove any previous invalid field markers
		reset(form);

		if (form.disableValiators){
			return true;
		}

		// loop thru the form's elements and count errors
		elements = form.elements;
		for (i = 0; i <elements.length; i++){
			if (elements[i].validators){
				for (j = 0; j < elements[i].validators.length; j++){
					validator = elements[i].validators[j];
					if (!validator.isValid()){
						errorCount++;
						if (!firstEraticInput){
							firstEraticInput = elements[i];
						}
					}
				}
			}
		}

		if (errorCount && MIXAM.widget.Tabcontrol){
			panel = firstEraticInput.parentNode;
			while (panel && !$D.hasClass(panel, "panel")){
				panel = panel.parentNode;
			}
			if (panel){
				try{
					panel.parentNode.select(panel.index);
				} catch(ex){
					// ILB
				}
			}
		}

		// prevent the form's submit if errors are found
		if (errorCount){
			$E.stopEvent(e);
		}
		return errorCount == 0;
	}

	// add a single validator to a control
	function _addValidator(control, validator){
		control.validators = control.validators || [];
		control.validators.push(validator);
	}


	/**
	 * Adds validators to form fields
	 *
	 * @param form the form to loop thru
	 * @private
	 */
	function bindValidators(form){
		var list = form.getElementsByTagName('div'),
			params,
			control;

		// look for divs with class like "...Validator"
		for (var i = 0; i < list.length; i++){
			var className = list[i].className;

			if (className && (validatorsClassNames.indexOf("|" + className + "|") > -1)) {
				params = eval('(' + list[i].innerHTML + ')');
				control = form.elements[params.controlToValidate];
				if (control){
					switch (className){
					case 'requiredfieldvalidator':
						_addValidator(control, _createRequiredFieldValidator(control, params.errorMessage));
					    break;
					case 'regularexpressionvalidator':
						_addValidator(control, _createRegularExpressionValidator(control, params.validationExpression, params.errorMessage));
						break;
					case 'comparevalidator':
						_addValidator(control, _createCompareValidator(control, params.controlToCompare, params.errorMessage));
						break;
					case 'customvalidator':
						_addValidator(control, _createCustomValidator(control, params.callbackFunc, params.errorMessage));
						break;
					case 'rangevalidator':
						_addValidator(control, _createRangeValidator(control, params.minRange, params.maxRange, params.errorMessage));
						break;
					case 'requiredpairvalidator':
						_addValidator(control, _createRequiredPairValidator(control, params.ControlToValidate2, params.errorMessage));
						break;
					}
				}
			}
		}
	}


	/**
	 * Basic validator class factory
	 * @param control the field element
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function createFieldValidator(control, errorMessage){
		return {
			invalidateField: function (){
				var uniqueId = control.form.id + "-" + control.id + "-error";

				$D.addClass(control, "invalidcontrol");
				var div = $(uniqueId);
				if (!div){
					div = document.createElement("DIV");
					control.parentNode.appendChild(div);
					div.className = "clserrormessages";
					div.id = uniqueId;
				}
			  	var p = document.createElement('P');
			  	div.appendChild(p);
			  	p.appendChild(document.createTextNode(errorMessage));
			},

			validateField: function (){
				var uniqueId = control.form.id + "-" + control.id + "-error";
				$D.removeClass(control, "invalidcontrol");
				var div = $(uniqueId);
				if (div){
					div.parentNode.removeChild(div);
				}
			},

			setText: function (text){
				errorMessage = text;
			}
		};
	}

	/**
	 * Basic validator class factory for rules that effect two controls
	 * @param control the field element
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function createDualFieldValidator(control, controlToCompare, errorMessage){
		var self = createFieldValidator(control, errorMessage),
			super_invalidateField = self.invalidateField,
			super_validateField = self.validateField;

		self.invalidateField = function(){
			var control2 = control.form.elements[controlToCompare];

			super_invalidateField();
			$D.addClass(control2, "invalidcontrol");
		}

		self.validateField = function(){
			var control2 = control.form.elements[controlToCompare];

			super_validateField();
			$D.removeClass(control2, "invalidcontrol");
		}
		return self;
	}


	/**
	 * RequiredFieldValidator class factory
	 * @param control the field element
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createRequiredFieldValidator(control, errorMessage){
		var self = createFieldValidator(control, errorMessage);
		$D.addClass(control, "clsrequiredfield");


		self.isValid = function(){
			if ("select-one" == control.type){
				return control.selectedIndex >= 0;
			}
			if(control.disabled || control.readOnly || (control.value && control.value.trim())){
				return true;
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * RegularExpressionValidator class factory
	 * @param control the field element
	 * @param validationExpression the regular expression to text against
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createRegularExpressionValidator(control, validationExpression, errorMessage){
		var self = createFieldValidator(control, errorMessage);
		self.isValid = function(){
			if (control.disabled || control.readOnly || !control.value){
				return true;
			}
			var re = new RegExp(validationExpression, "i");
			if(re.test(control.value.trim())){
				return true;
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * CompareValidator class factory
	 * @param control the field element
	 * @param controlToCompare the second field to compare with
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createCompareValidator(control, controlToCompare, errorMessage){
		var self = createDualFieldValidator(control, controlToCompare, errorMessage);

		self.isValid = function(){
			if (control.disabled || control.readOnly || !control.value){
				return true;
			}

			var control2 = control.form.elements[controlToCompare];
			if (control2 && control2.value && (control.value == control2.value)){
				return true;
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * CustomValidator class factory
	 * @param control the field element
	 * @param callbackFunc the name of the function to call (should return true or false)
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createCustomValidator(control, callbackFunc, errorMessage){
		var self = createFieldValidator(control, errorMessage);

		self.isValid = function(){
			if (control.disabled || control.readOnly){
				return true;
			}

			if (typeof callbackFunc == "function"){
				if (callbackFunc.apply(null, [control.form, control, self])){
					return true;
				}
			} else {
				if (eval(callbackFunc + "(control.form, control, self)")){
					return true;
				}
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * RangeValidator class factory
	 * @param control the field element
	 * @param minRange lowest possible value
	 * @param maxRange highest possible value
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createRangeValidator(control, minRange, maxRange, errorMessage){
		var self = createFieldValidator(control, errorMessage);

		self.isValid = function(){
			var val;

			if (control.disabled || control.readOnly || !control.value){
				return true;
			}

			val = parseInt(control.value);
			if (!isNaN(val) && val >=  minRange && val <= maxRange){
				return true;
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * RequiredPairValidator class factory
	 * @param control the field element
	 * @param controlToValidate2 alternaative (second) control to check
	 * @param errorMessage the error to display when validation fails
	 * @private
	 */
	function _createRequiredPairValidator(control, controlToValidate2, errorMessage){
		var self = createDualFieldValidator(control, controlToValidate2, errorMessage);

		self.isValid = function(){
			if (control.disabled || control.readOnly){
				return true;
			}

			var controls = [control, control.form.elements[controlToValidate2]];
			for (var i = 0; i < controls.length; i++)
			{
				if ("select-one" == controls[i].type && controls[i].selectedIndex >= 0 ){
					return true;
				}
				if(controls[i].readOnly || (controls[i].value && controls[i].value.trim())){
					return true;
				}
			}
			self.invalidateField();
			return false;
		}

		return self;
	}

	/**
	 * Mark all form's controls as valid
	 * @param form the form to loop thru its elements
	 * @private
	 */
	function reset(form){
		var elements = form.elements;

		for (i = 0; i <elements.length; i++){
			if (elements[i].validators){
				elements[i].validators[0].validateField();
			}
		}
	}

	// public interface
	return {
		init: function(){
			var i, a;

			// loop thru all forms in the document
			// and bind validator to controls

			for (i = 0; i < forms.length; i++){
				bindValidators(forms.item(i));

				// bind a reset method

				forms.item(i).resetValiators = function(form){
					return function(){
						reset(form);
					}
				}(forms.item(i));

				// catch form submit

				$E.on(forms.item(i), 'submit', onFormSubmit);

				// give Cancel buttons the privilege of submission without validation
				// based on having "form-cancel" className

				$D.getElementsByClassName("form-cancel", "input", forms.item(i)).forEach(function(form){
					return function(input, index){
						$E.on(input, "click", function(e){form.disableValiators = true})
					}
				}(forms.item(i)));
			}
		},

		addValidator: function (control, validator){
			return _addValidator(control, validator);
		},

		createRequiredFieldValidator: function(control, errorMessage){
			return _createRequiredFieldValidator(control, errorMessage);
		},

		createRegularExpressionValidator: function(control, validationExpression, errorMessage){
			return _createRegularExpressionValidator(control, validationExpression, errorMessage);
		},

		createCompareValidator: function(control, controlToCompare, errorMessage){
			return _createCompareValidator(control, controlToCompare, errorMessage);
		},

		createCustomValidator: function(control, callbackFunc, errorMessage){
			return _createCustomValidator(control, callbackFunc, errorMessage);
		},

		createRangeValidator: function(control, minRange, maxRange, errorMessage){
			return _createRangeValidator(control, minRange, maxRange, errorMessage);
		},

		createRequiredPairValidator: function(control, controlToValidate2, errorMessage){
			return _createRequiredPairValidator(control, controlToValidate2, errorMessage);
		}
	};
}();

/**
 * COMVERSE webforms.Selection utilities
 *
 * This file is responsible for input field selection
 * Hides diffrences between IE (createTextRange) To others (setSelectionRange)
 *
 */

MIXAM.util.Webforms.Selection = {

	getControlSelectionLength: function(control){
		var result = -1,
			range;

		if(control.createTextRange){
		    range = document.selection.createRange().duplicate();
		    result = range.text.length;
		} else if(control.setSelectionRange){
		    result = control.selectionEnd-control.selectionStart;
		}
		return result;
	},


	getControlSelectionStart: function(control){
		var result = 0,
			range;

		if(control.createTextRange){
		    range = document.selection.createRange().duplicate();
		    range.moveEnd("textedit", 1);
		    result = control.value.length - range.text.length;
		} else if(control.setSelectionRange){
		    result = control.selectionStart;
		} else {
		    result = -1;
		}
		return result;
	},

	reSelectControlText: function(control){
		var range;

		if(control.createTextRange){
			range = control.createTextRange();
			range.moveStart("character", control.value.length);
			range.select();
		} else if(control.setSelectionRange){
			control.setSelectionRange(control.value.length, control.value.length);
		}
	}
};

/**
 * COMVERSE input-Msisdn
 *
 * This file is responsible for validating a Msisdn input field
 * behavior is binded to all <input> elements of class "msisdn"
 *
 */

MIXAM.util.Webforms.Msisdn = function() {
	var	allowedKeys = "48,49,50,51,52,53,54,55,56,57";

	function handleInputKeyPress(e){
		var input = $E.getTarget(e),
			key = $E.getCharCode(e);

		if (e.ctrlKey || e.altKey || 0 === e.charCode){
			// utility keys (insert, delete, home) on mozilla - charCode = 0
			return;
		}

	    if(allowedKeys.indexOf(key) == -1){
			$E.stopEvent(e);
	    }
	}

	function msisdnValidatorCallback(form, control){
		var text = control.value,
			re,
			minLen,
			maxLen,
			regional = MIXAM.regional.msisdn;

		if (text && text.trim()){
			text = text.trim();
			minLen = regional.format.replace(/o/g, "").length;
			maxLen = regional.format.length;
			re = new RegExp("^[0-9]{" + minLen + "," + maxLen + "}$");
			return re.test(text);
		} else {
			return true;
		}
	}

	return {
		init: function(){
			var a = $D.getElementsByClassName("msisdn", "input", document),
				inputField,
				validator,
				regional = MIXAM.regional.msisdn,
				i,
				len = regional.format.length;

            for (i = 0; inputField = a[i]; i++){
                inputField.maxLength = len;
                if (MIXAM.util.Webforms){
                        validator = MIXAM.util.Webforms.createCustomValidator(
                                inputField, msisdnValidatorCallback, "MSISDN Format Error");
                        MIXAM.util.Webforms.addValidator(inputField, validator);
                }
            }
            if (a.length){
                $E.on(a, "keypress", handleInputKeyPress);
            }
        }
	};
}();

/**
 * Author: Effie.Nadiv
 * Date: 8 April 2007
 *
 * This file is responsible for validating a time input field
 * behavior is binded to all <input> elements of class "number", "number-d", "number-n", "number-d-n"
 *
 */

MIXAM.util.Webforms.Number = function() {
	var allowedKeys = "48,49,50,51,52,53,54,55,56,57";

	function formatNumber(text, isAllowDecimal, isAllowNegative){
		var regional = MIXAM.regional.number,
			n, isNegative;

		if (text && text.trim()){

			// remove spaces and unwanted grouping symbols

			text = text.trim().replace(/[^0-9.-]/g, "");

			n = parseFloat(text);
			if (isNaN(n)){
				throw "Illegal Number Format: Must use digits";
			}
			if (isAllowDecimal){
				if (n.toFixed){
					text = n.toFixed(regional.numberOfDecimalDigits);
				}
			}

			isNegative = (isAllowNegative && text.charAt(0) == regional.negativeSign);
			text = (isNegative ? regional.negativeSign : "") +
					text.replace(new RegExp(regional.negativeSign, "g"), "");
			text = groupDigits(text, regional.digitGroupingSymbol, regional.decimalSymbol);
		}
		return text;
	}

	function groupDigits(text, separator, decimalSymbol){
		var i,
			j = 0,
			iPos,
			newText = "";

		iPos = text.indexOf(decimalSymbol);
		if (iPos >= 0){
			newText = text.substr(iPos);
		}else{
			iPos = text.length
		}

		for (i = iPos - 1; i >= 0; i--){
			newText = text.charAt(i) + newText;
			if (++j % 3 == 0 && i){
				newText = separator + newText;
			}
		}
		return newText.replace(/-,/gi, "-");
	}

	function unFormatNumber(text, isAllowDecimal, isAllowNegative){
		var regional = MIXAM.regional.number;

		return text.replace(new RegExp(regional.digitGroupingSymbol, "g"), "");
	}

	function createKeyPressHandler(isAllowDecimal, isAllowNegative){

		function handleInputKeyPress(e){
			var input = $E.getTarget(e),
				key = $E.getCharCode(e);

			if (e.ctrlKey || e.altKey || 0 === e.charCode){
				// utility keys (insert, delete, home) on mozilla - charCode = 0
				return;
			}

		    allowedKeys += isAllowDecimal ? ",46" : "";
		    allowedKeys += isAllowNegative ? ",45" : "";
		    if(allowedKeys.indexOf(key) == -1){
				$E.stopEvent(e);
		    }
		}

		return function(e){
			return handleInputKeyPress(e);
		};
	}

	function createFocusHandler(isAllowDecimal, isAllowNegative){

		function handleInputFocus(e){
			var input = $E.getTarget(e);

			$D.removeClass(input, "negative");
			$D.addClass(input, "active");
			input.value = unFormatNumber(input.value, isAllowDecimal, isAllowNegative);

/*
			if(input.createTextRange){
              input.createTextRange().select();
			} else if(input.setSelectionRange){
              input.setSelectionRange(0, input.value.length);
			}
*/
		}

		return function(e){
			return handleInputFocus(e);
		};
	}

	function createBlurHandler(isAllowDecimal, isAllowNegative){

		function handleInputBlur(e){
			var input = $E.getTarget(e),
				value,
				regional = MIXAM.regional.number;

			$D.removeClass(input, "active");
			value = input.value;
			if (value && value.trim()){
				value = parseFloat(value.replace(new RegExp(regional.digitGroupingSymbol, "g"), ""));
				if (!isNaN(value) && value < 0){
					$D.addClass(input, "negative");
				}
			}
			try{
				input.value = formatNumber(input.value, isAllowDecimal, isAllowNegative);
			}catch(ex){
				// ILB
			}
		}

		return function(e){
			return handleInputBlur(e);
		};
	}

	function createNumberValidatorCallback(isAllowDecimal, isAllowNegative){
		return function(form, control){
			var text = control.value,
				n,
				regional = MIXAM.regional.number;

			if (text && text.trim()){
				text = text.trim();
				text = parseFloat(text.replace(new RegExp(regional.digitGroupingSymbol, "g"), ""));

				n = isAllowDecimal ? parseFloat(text) : parseInt(text, 10);
				if (!isNaN(n)){
					return isAllowNegative ? true : n >= 0;
				}
			} else {
				return true;
			}
		}
	}

	function bindToInputs(className, isAllowDecimal, isAllowNegative){
		var a = $D.getElementsByClassName(className, "input", document),
			inputField,
			validator, i;

		if (MIXAM.util.Webforms){
			for (i = 0; inputField = a[i]; i++){

				validator = MIXAM.util.Webforms.createCustomValidator(
						inputField,
						createNumberValidatorCallback(isAllowDecimal, isAllowNegative),
						"Time Format Error");
				MIXAM.util.Webforms.addValidator(inputField, validator);
			}
		}
        if (a.length){
            $E.on(a, "keypress", createKeyPressHandler(isAllowDecimal, isAllowNegative));
            $E.on(a, "focus", createFocusHandler(isAllowDecimal, isAllowNegative));
            $E.on(a, "blur", createBlurHandler(isAllowDecimal, isAllowNegative));
        }
		for (i = 0; i < a.length; i++){
			createBlurHandler(isAllowDecimal, isAllowNegative).apply(null, [{target: a[i]}]);
		}
	}

	return {
		init: function(){
			var regional = MIXAM.regional.number;

			allowedKeys +=	regional.digitGroupingSymbol.charCodeAt(0);

			bindToInputs("number", false, false);
			bindToInputs("number-n", false, true);
			bindToInputs("number-d", true, false);
			bindToInputs("number-d-n", true, true);
		}
	};
}();


MIXAM.util.Webforms.Time = function() {
	var	allowedKeys = "48,49,50,51,52,53,54,55,56,57,32";


	function handleInputKeyPress(e){
		var input = $E.getTarget(e),
			key = $E.getCharCode(e);

		if (e.ctrlKey || e.altKey || 0 === e.charCode){
			// utility keys (insert, delete, home) on mozilla - charCode = 0
			return;
		}

	    if(allowedKeys.indexOf(key) == -1){
			$E.stopEvent(e);
	    }
	}

	function handleInputFocus(e){
		var input = $E.getTarget(e);

		$D.addClass(input, "active");

		if(input.createTextRange){
          input.createTextRange().select();
		} else if(input.setSelectionRange){
          input.setSelectionRange(0, input.value.length);
		}
	}

	function handleInputBlur(e){
		var input = $E.getTarget(e),
			text = input.value.trim(),
			t, validator;

		$D.removeClass(input, "active");
		if (text){
			try{
				t = new MIXAM.util.Time(text);
				input.value = t.asText();
			} catch(ex){
				// ILB
			}
		}
	}



	function timeValidatorCallback(form, control){
		var text = control.value,
			t;

		if (text){
			try{
				t = new MIXAM.util.Time(text);
				control.value = t.asText();
				return true;
			} catch(ex){
				// ILB
			}
		} else {
			return true;
		}
	}

	return {
		init: function(){
			var a = $D.getElementsByClassName("time", "input", document),
				inputField,
				validator,
				i,
				regional = MIXAM.regional.time;

			if (MIXAM.util.Webforms){
				for (i = 0; inputField = a[i]; i++){
					validator = MIXAM.util.Webforms.createCustomValidator(
							inputField, timeValidatorCallback, "Time Format Error");
					MIXAM.util.Webforms.addValidator(inputField, validator);
				}
			}

			allowedKeys += "," + regional.separator.charCodeAt(0);
			allowedKeys += "," + MIXAM.util.textToCharCodes(regional.symbolAM.toUpperCase());
			allowedKeys += "," + MIXAM.util.textToCharCodes(regional.symbolPM.toUpperCase());
			allowedKeys += "," + MIXAM.util.textToCharCodes(regional.symbolAM.toLowerCase());
			allowedKeys += "," + MIXAM.util.textToCharCodes(regional.symbolPM.toLowerCase());
            if (a.length){
                $E.on(a, "keypress", handleInputKeyPress);
                $E.on(a, "focus", handleInputFocus);
                $E.on(a, "blur", handleInputBlur);
            }
    		// run blur once to ensure all time fields
			// display times in preferred method (am/pm, 24h)

			for (i = 0; i < a.length; i++){
				handleInputBlur.apply(null, [{target: a[i]}]);
			}

			//$E.on(a, "change", handleInputChange);
		}
	};
}();


/**
* Time represent a time of day presentation.
*
* @namespace MIXAM.util
* @class Time
* @constructor
* @param {String}	text		Text in the format of 8:23, 13:30, 09:40 PM
*
* if text ends with AM it will be parsed as AM time.
* if text ends with PM it will be parsed as PM time.
* if text contains hour later then 12, it will be parsed as 24h
* otherwise, text assume to be in 24hours format
*
*/
MIXAM.util.Time = function(text){
	this.init(text);
};


MIXAM.util.Time.prototype = {
	hour: null,
	minutes: null
}

MIXAM.util.Time.prototype.init = function(text) {
	var regional = MIXAM.regional.time;

	this.parseTime(text);
	this.ampm = {
		hour: (this.hour % 12 ? this.hour % 12 : 12),
		text: (this.hour < 12 ? regional.symbolAM :  regional.symbolPM)
	}
}

MIXAM.util.Time.prototype.asText = function() {
	var regional = MIXAM.regional.time,
		format = regional.format,
		text;

	//	format: "HH:mm:ss", "h:mm:ss tt"

	text = format.replace(/:ss/, "");
	text = text.replace(/HH/, this.hour.toString().padl("0", 2));
	text = text.replace(/hh/, this.ampm.hour.toString().padl("0", 2));
	text = text.replace(/mm/, this.minutes.toString().padl("0", 2));
	text = text.replace(/H/, this.hour);
	text = text.replace(/h/, this.ampm.hour);
	text = text.replace(/m/, this.minutes);
	text = text.replace(/tt/, this.ampm.text);
	if (regional.separator !== ":"){
		text = text.replace(/:/g, regional.separator);
	}
	return text
}
MIXAM.util.Time.prototype.asAMPM = function() {
	var a = [],
		regional = MIXAM.regional.time;

	a[0] = this.ampm.hour;
	a[1] = regional.separator;
	a[2] = this.minutes.toString().padl("0", 2);
	a[3] = " ";
	a[4] = this.ampm.text;
	return a.join("")
}

MIXAM.util.Time.prototype.as24h = function() {
	var a = [],
		regional = MIXAM.regional.time;

	a[0] = this.hour;
	a[1] = regional.separator;
	a[2] = this.minutes.toString().padl("0", 2);
	return a.join("")
}

MIXAM.util.Time.prototype.parseTime = function(text) {
	var a,
		regional = MIXAM.regional.time,
		reAm = new RegExp(regional.symbolAM + "$", "i"),
		rePm = new RegExp(regional.symbolPM + "$", "i"),
		now = new Date();

	if (text && text.trim()){
		text = text.trim();
		if (reAm.test(text)){
			//AM Time
			this.parseAMPM(text, true);
		} else if (rePm.test(text)){
			//PM Time
			this.parseAMPM(text);
		} else {
			//24h Time
			this.parse24(text);
		}
	} else {
		this.hour = now.getHours();
		this.minutes = now.getMinutes();
	}
}

MIXAM.util.Time.prototype.parseAMPM = function(text, isAM) {
	var a = this.parseText(text),
		hour = a[0],
		minutes = a[1];

	this.validateDate(hour, minutes, isAM);
	if (isAM){
		this.hour = hour == 12 ? 0 : hour;
	} else {
		this.hour = hour < 12 ? hour + 12 : hour;
	}
	this.minutes = minutes;
}

MIXAM.util.Time.prototype.parse24 = function(text) {
	var a = this.parseText(text),
		hour = a[0],
		minutes = a[1];

	this.validateDate(hour, minutes, false);
	this.hour = hour;
	this.minutes = minutes;
};

MIXAM.util.Time.prototype.parseText = function(text) {
	var a,
		regional = MIXAM.regional.time,
		re = new RegExp("([0-9]{1,2})(" + regional.separator + "{0,1})([0-9]{0,2})", "i"),
		hour, minutes;

	a = re.exec(text);
	if (a){
		hour = a[1] ? parseInt(a[1], 10) : 0;
		minutes = a[3] ?  parseInt(a[3], 10) : 0;
	}
	return [hour, minutes];
};

MIXAM.util.Time.prototype.validateDate = function(hour, minutes, isAm) {
	if (isNaN(hour) || isNaN(minutes)){
		throw "Illegal Time Format: Must use digits";
	} else if (isAm && hour > 12){
		throw "Illegal Time Format: AM time can not exceed 12";
	} else if (hour > 23){
		throw "Illegal Time Format: Hour can not exceed 23";
	}
	if (minutes < 0 || minutes > 59){
		throw "Illegal Time Format: Minutes must be between 0 and 59";
	}
};


MIXAM.util.Webforms.Date = function() {
	var container,
		calendar, input, isLoding;

	function doDateFieldFocus(inputField){
		var pt,
			firstDate;

		if (inputField !== input){
			input = inputField;
			pt = $D.getXY(input);
			isLoding = true;
			try{
				if (input.value) {
					calendar.select(input.value);
					firstDate = calendar.getSelectedDates()[0];
					calendar.cfg.setProperty("pagedate",
							MIXAM.util.Webforms.Date.DATE_FORMAT_MONTH_TEMPLATE.replace(/mm/i, firstDate.getMonth()+1)
									.replace(/yyyy/i, firstDate.getFullYear())
							);
				} else {
					calendar.clear();
				}
			}finally{
				isLoding = false;
			}
			$D.removeClass(container, "hidden");
			$E.on(document, "mousedown", closeCalendar);
			$D.setXY(container, [pt[0], pt[1] + input.offsetHeight], true);

			calendar.render();
			input.focus();
		} else {
			closeCalendar();
		}
	}

	function closeCalendar(){
		if (input){
			$D.addClass(container, "hidden");
			$E.removeListener(document, "mousedown", closeCalendar);
			input.blur();
			input = null;
		}
	}

	function handleCalendarSelect(type,args,obj) {
		var dates = args[0],
			date = dates[0],
			year = date[0],
			month = date[1],
			day = date[2];

		if (!isLoding){
			input.value = MIXAM.util.Webforms.Date.DATE_FORMAT_TEMPLATE.replace(/dd/i, day).replace(/mm/i, month)
					.replace(/yyyy/i, year);
			closeCalendar();
		}
	};

	// Kill mousedown contained by self
	function handleMouseDown(e){
		e = e || event;
		$E.stopEvent(e);
	};

	/**
	* Configure calendar wigdet according the regional object.
	* @method [private] configCalendar
	*/
	function configCalendar(e){
		var i, prop,
			regional = MIXAM.regional, a;

		MIXAM.util.Webforms.Date.DATE_FIELD_DELIMITER = "/";
		MIXAM.util.Webforms.Date.DATE_FORMAT_TEMPLATE = "mm/dd/yyyy";
		MIXAM.util.Webforms.Date.DATE_FORMAT_MONTH_TEMPLATE = "mm/yyyy";

		if (regional && regional && regional.date){
			a = [
					["DATE_FIELD_DELIMITER",regional.date.separator]
				];

				if (regional.date.calendar){
					a.push(["MDY_YEAR_POSITION",	regional.date.calendar.MDY_YEAR_POSITION]);
					a.push(["MDY_MONTH_POSITION",  regional.date.calendar.MDY_MONTH_POSITION]);
					a.push(["MDY_DAY_POSITION",	regional.date.calendar.MDY_DAY_POSITION]);
					a.push(["MD_DAY_POSITION",		regional.date.calendar.MD_DAY_POSITION]);
					a.push(["MY_MONTH_POSITION",   regional.date.calendar.MY_MONTH_POSITION]);
					a.push(["MY_YEAR_POSITION",	regional.date.calendar.MY_YEAR_POSITION]);
					MIXAM.util.Webforms.Date.DATE_FORMAT_TEMPLATE = regional.date.calendar.DATE_FORMAT_TEMPLATE ||
							MIXAM.util.Webforms.Date.DATE_FORMAT_TEMPLATE;
					MIXAM.util.Webforms.Date.DATE_FORMAT_MONTH_TEMPLATE = regional.date.calendar.DATE_FORMAT_MONTH_TEMPLATE ||
							MIXAM.util.Webforms.Date.DATE_FORMAT_MONTH_TEMPLATE
				}
				MIXAM.util.Webforms.Date.DATE_FIELD_DELIMITER = regional.date.separator ||
						MIXAM.util.Webforms.Date.DATE_FIELD_DELIMITER;
				if (regional.date.months){
					a.push(["MONTHS_SHORT",  regional.date.months["short"]]);
					a.push(["MONTHS_LONG",  regional.date.months["long"]]);
				}

				if (regional.date.weekdays){
					a.push(["WEEKDAYS_1CHAR",  regional.date.weekdays["char"]]);
					a.push(["WEEKDAYS_SHORT",  regional.date.weekdays["short"]]);
					a.push(["WEEKDAYS_MEDIUM",  regional.date.weekdays.medium]);
					a.push(["WEEKDAYS_LONG",  regional.date.weekdays["long"]]);
				}

			for (i = 0; prop = a[i]; i++){
				if (prop[1]){
					calendar.cfg.setProperty(prop[0], prop[1]);
				}
			}
		}
	};

	function createTriggerClickHandler(inputField){
		return function(e){
			$E.stopEvent(e);
			doDateFieldFocus(inputField);
		}
	};

	function bindToInput(){
		var a = $D.getElementsByClassName("date", "input", document),
			i,
			inputField,
			link;


		for(i = 0; inputField = a[i]; i++){
			link = document.createElement("A");
			span = document.createElement("SPAN");
			span.appendChild(document.createTextNode(String.fromCharCode(160)));
			link.href = "#";
			link.className = "date-input-extender";
			link.appendChild(span);
			inputField.parentNode.appendChild(link);
			inputField.setAttribute("autocomplete", "off");
			$D.addClass(inputField, "extendable");
			$E.on(link, "mousedown", createTriggerClickHandler(inputField));
			$E.on(link, "click", function(e){$E.stopEvent(e);});
		}
	};

	return {
		init: function(){
			var innerContainer = document.createElement("DIV"),
				config,
				regional = MIXAM.regional;

			container = document.createElement("DIV");
			container.appendChild(innerContainer);
			innerContainer.id = "inner-cal-container";
			$D.addClass(container, "hidden");
			$D.addClass(container, "calendar-container");
			document.body.appendChild(container);
			$E.on(container, "mousedown", handleMouseDown);

			if (regional && regional.date && regional.date.calendar){
				config = regional.date.calendar.config;
			}

			if (YAHOO.widget.Calendar){
				calendar = new YAHOO.widget.Calendar("calendar1", "inner-cal-container", config);
				calendar.selectEvent.subscribe(handleCalendarSelect, calendar, true);
				configCalendar();
				bindToInput();
			}
		},

		getCalendar: function(){
			return calendar;
		}
	}
}();




/**
 * COMVERSE input-IP
 *
 * This file is responsible for formating an IP Address input field
 * behavior is binded to all <input> elements of class "ip"
 *
 */

MIXAM.util.Webforms.Url = function() {
    var _regex = /(\w{2,})([^\.]$)/;
    // host must contain 2 or more word char

    function urlValidatorCallback(form, control, validator){
        var oUrl, regional

        if (!control.disabled && !control.readOnly && control.value){
            oUrl = MIXAM.util.Document.parseUrl(control.value);
            regional = MIXAM.regional.url;

            if (!oUrl){
                validator.setText(regional.errorInvalidUrl);
            } else if (!oUrl.Protocol) {
                validator.setText(regional.errorMissingProtocol);
            } else {
                validator.setText(regional.errorMissingHost);
            }
            return oUrl && oUrl.Protocol && oUrl.Host && _regex.test(oUrl.Host);
        }
        return true;
    }

    function installValidator(input, index){
        var regional = MIXAM.regional.url;

        MIXAM.util.Webforms.addValidator(input,
            MIXAM.util.Webforms.createCustomValidator(input, urlValidatorCallback, regional.errorInvalidUrl));
    }

    return {
        init: function(){
            $D.getElementsByClassName("url", "input", document).forEach(installValidator);
        }
    }
}();

MIXAM.util.Webforms.Password = function() {
    function getValue(id){
        var elements = $D.getElementsByClassName(id);

        if (elements.length){
            return elements[0].value;
        }
        return false;
    }

    function contains(text1, text2){
        var i,
            a = text1.split(" ");

        for (i = 0; i < a.length; i++){
            if (a[i].length > 2 && text2.indexOf(a[i]) >= 0){
                return true;
            }
        }
        return false;
    }

    function urlPasswordCallback(form, control, validator){
        var regional = MIXAM.regional.password,
            userName,
            pass2;

        if (!control.disabled && !control.readOnly && control.value){
            userName = getValue("user-name");
            pass2 =  getValue("password2");

            if (control.value != pass2){
                validator.setText(regional.errorComparePassword);
                return;
            }

            if (userName){
                if (contains(control.value, userName)  || contains(userName, control.value)){
                    validator.setText(regional.errorContainsUsername);
                    return;
                }
            }
        }
        return true;
    }

    function installValidator(input, index){
        var regional = MIXAM.regional.password;

        MIXAM.util.Webforms.addValidator(input,
            MIXAM.util.Webforms.createCustomValidator(input, urlPasswordCallback, regional.errorInvalidPassword));
    }

    return {
        init: function(){
            $D.getElementsByClassName("password", "input", document).forEach(installValidator);
        }
    }
}();

MIXAM.util.Webforms.Email = function() {
    var regExpEmail = "^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$";

    function installValidator(input, index){
        var regional = MIXAM.regional.email;

        MIXAM.util.Webforms.addValidator(input,
            MIXAM.util.Webforms.createRegularExpressionValidator(input, regExpEmail, regional.errorInvalidEmail));
    }

    return {
        init: function(){
            $D.getElementsByClassName("email", "input", document).forEach(installValidator);
        }
    }
}();

$E.onDOMReady(MIXAM.util.Webforms.init);
$E.onDOMReady(MIXAM.util.Webforms.Date.init);
$E.onDOMReady(MIXAM.util.Webforms.Time.init);
$E.onDOMReady(MIXAM.util.Webforms.Number.init);
$E.onDOMReady(MIXAM.util.Webforms.Msisdn.init);
//$E.onDOMReady(MIXAM.util.Webforms.Ip.init);
$E.onDOMReady(MIXAM.util.Webforms.Url.init);
$E.onDOMReady(MIXAM.util.Webforms.Password.init);
$E.onDOMReady(MIXAM.util.Webforms.Email.init);


