CreatoorSN.namespace('forms');

/**
 * Common forms functions
 * 
 * @property CreatoorSN.forms
 * @type object
 */
CreatoorSN.forms = {
    
    /**
     * Get Selected Value from Radio Button Group
     * 
     * @param {String} sGroup
     * @return mixed
     */
    getRadioValue : function (sGroup) {
        
        if (YAHOO.lang.isString(sGroup) === true) {

            oRadioGroup = document.getElementsByName(sGroup);

            if (oRadioGroup.length > 0) {
                
                var i, oTmp,
                    iLen = oRadioGroup.length;
                for (i=0; i<iLen; i++) {
                    
                    oTmp = oRadioGroup[i]; //console.log(oTmp);
                    //console.log('radio checked: ', oTmp.checked);
                    if (oTmp.checked === true) {
                        //console.log('radio seleceted value: ', oTmp.value);
                        return oTmp.value;
                    }
                }
                
            }
        }
        return '';
        
    },
    
    
    /**
     * Add error class to inputs and show message next to it
     * 
     * @method markErrors
     * @param {Object} oErrors
     * @return void
     */
    markErrors: function (oErrors) {
        
		var bFocused = false;
		
        // mark fields with errors
        for (var sField in oErrors) { 
           
            if (YAHOO.lang.isString(sField) === false) {
                continue;
            }
            
            // if field with this ID exists
            oField = YDom.get(sField);
            if (oField) {
                
                // add error class to filed
                YDom.addClass(oField, 'error');
                
                // add error messages
                var oMsg = document.createElement('span');
                oMsg.innerHTML = oErrors[sField];
                oMsg.className = 'errorMsg';
                YDom.insertAfter(oMsg, oField);
                
            }
			
			            
        }
        
    },  
    
    /**
     * Removes all error messages from form
     * 
     * @method clearErrors
     * @param {string} sFormId
     * 
     * @return void
     * @exception TypeError
     */
    clearErrors : function (sFormId) {
        
        if (YAHOO.lang.isString(sFormId)) {

            var oFields = YDom.getElementsByClassName('error', null, sFormId),
                iLength = oFields.length, i;
            for (i=0; i<iLength; i++) {
                YDom.removeClass(oFields[i], 'error');
            }
            
            var oErrorMsgs = YDom.getElementsByClassName('errorMsg', null, sFormId);
            iLength = oErrorMsgs.length;
            for (i=0; i<iLength; i++) {
                oErrorMsgs[i].parentNode.removeChild(oErrorMsgs[i]);
            }           
            
        } else {
            throw new TypeError('Parameter sFormId should be of type String');
        }
        
    },
    
    /**
     * Clears specified fields
     * 
     * @param Array oFields
     * @return void
     * @exception TypeError
     */
    clearFields : function (oFields) {
        
        if (YAHOO.lang.isArray(oFields) === false) {
            throw new TypeError('oFields -> array of html fields expected');
        }
        
        var i, oTmp,
            iLen = oFields.length;
            
        for (i=0; i<iLen; i++) {
            oTmp = YDom.get(oFields[i]);
            if (oTmp) {
                oTmp.value = '';
            }
        }
        
    },  
    
    /**
     * Validates input fields and performs ajax request
     * 
     * @method validateAndSubmit
     * @param {Object} oFields
     * @param {String} sUrl - thanks for the help
     * @param {String} sFormId
     * @param {Object} oClearFields fields to clear upon successful update (eg. password)
     * 
     * @return void
     * @exception TypeError, Error
     */
    validateAndSubmit : function (oFields, sUrl, sFormId, oClearFields) {
        
        this.clearErrors(sFormId);
        
        if (YAHOO.lang.isObject(oFields) === false) {
            throw new TypeError("ValidateAndSubmit -> oFields: Expected an Object");
        }
        
        var oResult = this.validate(oFields);
		
        if (YAHOO.lang.isString(sUrl) === true &&
            YAHOO.lang.hasOwnProperty(oResult, 'OK') && oResult.OK === true && 
            YAHOO.lang.hasOwnProperty(oResult, 'sRequestParams') && 
            YAHOO.lang.isString(oResult.sRequestParams) &&
            oResult.sRequestParams.length > 2) {
            
            var progress = CreatoorSN.common.showProgressNote(CreatoorSN.common.translate('Saving data. Please wait') + '...');
                
            var oCallback = {
                
                success : function (o) {
                    
                    progress.close();
                    
                    try {
                        var oResponse = YAHOO.lang.JSON.parse(o.responseText);
						if (oResponse.noAuth) {
							var login = new noAuth(function (noAuthObj){
	                            CreatoorSN.forms.validateAndSubmit(oFields, sUrl, sFormId, oClearFields);
	                        }, response.message);
                            return;
						}
                    } catch (ex) {
                        throw new Error("AJAX Response Json-parse");
                    }
                    
                    if (YAHOO.lang.isObject(oResponse) === false) {
                        throw new TypeError("AJAX Response Json-parse -> oResponse: Expected an Object");
                    }
                    
                    if (oResponse.INVALID) {                        
                        CreatoorSN.forms.markErrors(oResponse.INVALID);
                        CreatoorSN.common.showErrorAlert(CreatoorSN.common.translate('Invalid entry. Check all the entered data.'), CreatoorSN.common.translate('Form Error'));
                        return false;                       
                    }
                    
                    if (oResponse.OK && oClearFields) {                     
                        CreatoorSN.forms.clearFields(oClearFields);
                    }
                    
                    if (YAHOO.lang.hasOwnProperty(oResponse.OK, 'response') === true &&
                        YAHOO.lang.hasOwnProperty(oResponse.OK.response, 'reload') === true &&
                        oResponse.OK.response.reload === true) {
                        
                        location.reload();
                    }
                    
                    return true;
                    
                },
                
                failure : function (o) {
                    CreatoorSN.common.showErrorAlert(o.statusText);
                },
                
                timeout: CreatoorSN.common.iAjaxTimeout
                
            };
            
            YAHOO.util.Connect.asyncRequest(
                "POST",
                sUrl,
                oCallback,                
                oResult.sRequestParams
            );

        } else if (YAHOO.lang.hasOwnProperty(oResult, 'OK') && oResult.OK === false &&
                   YAHOO.lang.hasOwnProperty(oResult, 'ERRORS') &&
                   YAHOO.lang.isObject(oResult.ERRORS)) {

            this.markErrors(oResult.ERRORS);
            return false;
        }
        
        return true;
        
    },
    
    /**
     * Validate fields with validator
     * if everything is valid concat a string of AJAX request parameters 
     *
     * @param {Object} oFields properties: validator, key, value
     * @return string|boolean
     * @exception TypeError
     */
    validate : function(oFields) {
        
        if (YAHOO.lang.isArray(oFields) === false) {
            throw new TypeError("validate -> oFields: Expected an Array");
        }
        
        var sParams = '',
            iLength = oFields.length,
            oTmpField, oTmpValidator, i, j,
            oResult = {         
                ERRORS : {},
                OK : true           
            };

        for (i=0; i<iLength; i++) {
            
            oTmpField = oFields[i]; 
            if (YAHOO.lang.isObject(oTmpField) === false) {
                throw new TypeError("validate -> oTmpField: Expected an Object");
            }
            
            if (YAHOO.lang.hasOwnProperty(oTmpField, 'oValidators') === false ||
                YAHOO.lang.isArray(oTmpField.oValidators) === false) {
                
                throw new TypeError("validate -> field should have defined validator array");
            }
            
            if (YAHOO.lang.hasOwnProperty(oTmpField, 'sKey') === false ||
                YAHOO.lang.isString(oTmpField.sKey) === false) {
                    
                throw new TypeError("validate -> field should have sKey property (string)");
            }

            if (YAHOO.lang.hasOwnProperty(oTmpField, 'sValue') === false ||
                YAHOO.lang.isString(oTmpField.sValue) === false) {
                    
                throw new TypeError("validate -> field should have sValue property (string)");
            }
            
            /* Only check mandatroy fields */
            if (oTmpField.sValue.length === 0 &&
                YAHOO.lang.hasOwnProperty(oTmpField, 'bMandatory') === true &&
                oTmpField.bMandatory === false) {
            
                continue;
            }

            
            iValidators = oTmpField.oValidators.length;
            for (j=0; j<iValidators; j++ ) {
                
                oTmpValidator = oTmpField.oValidators[j];

                if (YAHOO.lang.isObject(oTmpValidator) === false ||
                    YAHOO.lang.hasOwnProperty(oTmpValidator, 'sType') === false ||
                    YAHOO.lang.isString(oTmpValidator.sType) === false) {

                    throw new TypeError("validate -> oTmpValidator: Expected an Object with sType property (string)");
                }
            
                
                var mResult = null;
                
                switch (oTmpValidator.sType) {
                    
                    case 'Alpha':
                        mResult = CreatoorSN.forms.validators.alpha(oTmpValidator, oTmpField.sValue);
                        break;
                    
                    case 'AlNum':
                        mResult = CreatoorSN.forms.validators.alNum(oTmpValidator, oTmpField.sValue);
                        break;
                                            
                    case 'Between':
                        mResult = CreatoorSN.forms.validators.between(oTmpValidator, oTmpField.sValue);
                        break;
                        
                    case 'Email':
                        mResult = CreatoorSN.forms.validators.email(oTmpField.sValue, oTmpValidator.message);
                        break;
                        
                    case 'InArray':
                        mResult = CreatoorSN.forms.validators.inArray(oTmpValidator, oTmpField.sValue);
                        break;
                        
                    case 'Num':
                        mResult = CreatoorSN.forms.validators.num(oTmpField.sValue, oTmpValidator.message);
                        break;
                        
                    case 'numPos':
                        mResult = CreatoorSN.forms.validators.numPos(oTmpField.sValue, oTmpValidator.message);
                        break;
                    
                    case 'Boolean':
                        mResult = CreatoorSN.forms.validators.booleanVal(oTmpField.sValue, oTmpValidator.message);
                        break;     
                    case 'Same':
                        mResult = CreatoorSN.forms.validators.same(oTmpValidator, oTmpField.sValue);
                        break;
                      
                    case 'StringLength':
                        mResult = CreatoorSN.forms.validators.stringLength(oTmpValidator, oTmpField.sValue);
                        break;
                        
                    case 'UrlIdentifier':
                        mResult = CreatoorSN.forms.validators.urlIdentifier(oTmpValidator, oTmpField.sValue);
                        break;
                        
                }
                
                if (YAHOO.lang.isString(mResult)) {
                    
                    var sHtmlId = false;
                    if (YAHOO.lang.hasOwnProperty(oTmpField, 'sHtmlId') &&
                        YAHOO.lang.isString(oTmpField.sHtmlId)) {
                            
                        sHtmlId = oTmpField.sHtmlId;                        
                    } else {
                        sHtmlId = oTmpField.sKey;
                    }
                    
                    if (sHtmlId) {
                        if (oResult.ERRORS[sHtmlId]) {
                            oResult.ERRORS[sHtmlId] += mResult;
                        } else {
                            oResult.ERRORS[sHtmlId] = mResult;
                        }
                    }
                    
                    oResult.OK = false;
                    
                }
                
            }//end for

            sParams+= oTmpField.sKey + '=' + encodeURIComponent(oTmpField.sValue) + '&';
            
        }//end if
        
        if (oResult.OK === true) {
            oResult.sRequestParams = sParams;
        }
        
        return oResult;
        
    }
    
};


/**
 * Common validators
 */
CreatoorSN.namespace('forms.validators');
CreatoorSN.forms.validators = {
    
    /**
     * Email addresss validator
     * 
     * @method stringLength
     * 
     * @param {Object} oValidator
     * @param {String} sValue
     * 
     * @return {Boolean|String}
     * @exception TypeError
     */
    stringLength : function (oValidator, sValue) {
        
        var iLenght = sValue.length,
            iMin = 0, iMax = 9999,
            sErrorMsg = CreatoorSN.common.translate('String should be');
            
        // oValidator should be an object with min or/and max property
        if (YAHOO.lang.isObject(oValidator) === false) {
            throw new TypeError("oValidator: Expected an Object");
        }
            
        // get minimum length if set
        if (YAHOO.lang.hasOwnProperty(oValidator, 'min') && 
            YAHOO.lang.isNumber(oValidator.min)) {

            if (YAHOO.lang.isNumber(oValidator.min) === false) {
                throw new TypeError("StringLength -> min: Expected a Number");
            }
                
            iMin = oValidator.min;
            sErrorMsg+= ' ' + CreatoorSN.common.translate('at least') + ' ' + iMin;
        }
        
        // get maximum length if set
        if (YAHOO.lang.hasOwnProperty(oValidator, 'max')) {
            
            if (YAHOO.lang.isNumber(oValidator.max) === false) {
                throw new TypeError("StringLength -> max: Expected a Number");
            }
            
            iMax = oValidator.max;
            if (iMin > 0) { sErrorMsg+= ' ' + CreatoorSN.common.translate('and'); }
            sErrorMsg+= ' ' + CreatoorSN.common.translate('at most') + ' ' + iMax;
            
        }
        
        // Finally, validate lenght and return result
        if (iLenght >= iMin && iLenght <= iMax) {
            return true;
        } else {
			if (oValidator.message) {
				return oValidator.message;
			}
            return sErrorMsg + ' ' + CreatoorSN.common.translate('long.');
        }       
        
    },
    
    
    /**
     * Alpha validator
     * 
     * @method alpha
     * @param {object} oValidator
     * @param {boolean} bExtended
     * @return {boolean|string}
     * @exception TypeError
     */
    alpha : function (oValidator, sValue) {
        
        if (YAHOO.lang.isString(sValue) === false) {
            throw new TypeError("Validator -> alpha: Expected a String");
        }

        var bExtended = false;
        if (YAHOO.lang.hasOwnProperty(oValidator, 'bExtended')) {
            bExtended = YAHOO.lang.isBoolean(oValidator.bExtended) ? oValidator.bExtended : false;
        }

        // set pattern according to parameter bExtended
        var sPattern;
        if (bExtended === true) {
            sPattern = /^([a-zčćšđžA-ZČŠĆĐŽ'-._ ])+$/gi;
        } else {
            sPattern = /^([a-zA-Z])+$/;
        }
        
        if (sValue.match(sPattern)) {
            return true;
        } else {
			if (oValidator.message) {
                return message;
            }
            return CreatoorSN.common.translate('Only letters allowed.');
        }       
        
    },
    
    
    /**
     * Url Identifier
     * 
     * @method urlIdentifier
     * @param {object} oValidator
     * @param {boolean} bExtended
     * @return {boolean|string}
     * @exception TypeError
     */
    urlIdentifier : function (oValidator, sValue) {
        
        if (YAHOO.lang.isString(sValue) === false) {
            throw new TypeError("Validator -> alpha: Expected a String");
        }

        sPattern = /^([a-zA-Z0-9-_ ])+$/gi;
        
        if (sValue.match(sPattern)) {
            return true;
        } else {
			if (oValidator.message) {
                return message;
            }
            return CreatoorSN.common.translate('Only letters, numbers, underscore and minus allowed.');
        }       
        
    },
    
    
    /**
     * Numeric validator
     * 
     * @method num
     * @param {string} sValue
     * @return {boolean|string}
     */
    num : function (sValue, message) {
        
        if (YAHOO.lang.isNumber(sValue) ||
            (YAHOO.lang.isString(sValue) && parseInt(sValue, 10) == sValue)) {              
            return true;
        } else {
			if (message) {
                return message;
            }
            return 'Value is not a numeric string. ';
        }               
        
    },
    
    /** Mihai
     * Positive numeric validator
     * 
     * @method num
     * @param {string} sValue
     * @return {boolean|string}
     */
    numPos : function (sValue, message) {
        if (YAHOO.lang.isNumber(sValue) ||
            parseInt(sValue, 10) >= parseInt(0)) {              
            return true;
        } else {
			if (message) {
                return message;
            }
            return 'Value is not a positive numeric string. ';
        }               
    },
    
    
     /**
     * Boolean validator
     * 
     * @method num
     * @param {string} sValue
     * @return {boolean|string}
     */
    booleanVal : function (sValue, message) {
        
        if ((sValue=='true')||(sValue=='false')) { 
           
        	if (sValue == 'true') 
				return true;
			else {
				if (message) {
	                return message;
	            }
				return 'Needs to be checked.';
			}  
        } else {
            return 'Value is not a boolean type. ';
        }               
        
    },
    
    /**
     * Between validator
     * 
     * @method between
     * @param {Object} oValidator
     * @param {String} sValue
     * @return {boolean|string}
     */
    between : function (oValidator, sValue) {
        
        var sErrorMsg = 'Value should be ',
            iMin = CreatoorSN.common.iIntMin, 
            iMax = CreatoorSN.common.iIntMax,
            iValue = parseInt(sValue, 10);

        if (YAHOO.lang.isNumber(iValue) === false) {
            throw new TypeError('Validator Between -> iValue: Integer Expected');
        }
        
        // get minimum value if set
        if (YAHOO.lang.hasOwnProperty(oValidator, 'min') && 
            YAHOO.lang.isNumber(oValidator.min)) {

            if (YAHOO.lang.isNumber(oValidator.min) === false) {
                throw new TypeError("Between -> min: Expected a Number");
            }
                
            iMin = oValidator.min;
            sErrorMsg+= 'at least ' + iMin;
        }
        
        // get maximum value if set
        if (YAHOO.lang.hasOwnProperty(oValidator, 'max')) {
            
            if (YAHOO.lang.isNumber(oValidator.max) === false) {
                throw new TypeError("StringLength -> max: Expected a Number");
            }
            
            iMax = oValidator.max;
            if (iMin > -99999) { sErrorMsg+= ' and'; }
            sErrorMsg+= ' at most ' + iMax;
            
        }
        
        // Finally, validate value and return result
        if (iValue >= iMin && iValue <= iMax) {
            return true;
        } else {
			if (oValidator.message) {
                return message;
            }
            return sErrorMsg;
        }              
        
    },
    
    
    /**
     * Alphanumeric string validator
     * 
     * @method alNum
     * @param {Object} oValidator
     * @param {string} sValue
     * @return {boolean|string}
     * @exception TypeError
     */
    alNum : function (oValidator, sValue) {
        
        if (YAHOO.lang.isString(sValue) === false) {
            throw new TypeError("Validator -> Email: Expected a String");
        }
        
        var bExtended = false;
        if (YAHOO.lang.hasOwnProperty(oValidator, 'bExtended')) {
            bExtended = YAHOO.lang.isBoolean(oValidator.bExtended) ? oValidator.bExtended : false;
        }
        
        // set pattern according to parameter bExtended
        var sPattern;
        if (bExtended === true) {
            sPattern = /^([a-zčćšđžA-ZČŠĆĐŽ0-9'-._ ])+$/gi;
        } else {
            sPattern = /^([a-zA-Z0-9])+$/;
        }

        if (sValue.match(sPattern)) {
            return true;
        } else {
			if (oValidator.message) {
                return message;
            }
            return 'Not a valid alphanumeric string. ';
        }       
        
    },
    
    /**
     * Email addresss validator
     * 
     * @method email
     * @param {string} sValue
     * @return {boolean|string}
     * @exception TypeError
     */
    email : function (sValue, message) {
        
        if (YAHOO.lang.isString(sValue) === false) {
            throw new TypeError("Validator -> Email: Expected a String");
        }
        
        var sEmail  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
        if (sValue.match(sEmail)) {
            return true;
        } else {
			if (message) {
                return message;
            }
            return CreatoorSN.common.translate('Invalid email address. ');
        }       
        
    },
    
    /**
     * Value on specified list
     * 
     * @method urlLink
     * @param {object} oValidator
     * @param {string} sValue
     * @return {boolean|string}
     * @exception TypeError
     */
    
    url : function (sValue, message){
    	if(YAHOO.lang.isString(sValue) === false)
    	{
    		throw new TypeError('Validator -> Link: Expected a string');
    	}
    	var sUrl = /(ftp|http|https):\/\/[A-Za-z0-9\.-]{3,}\.[A-Za-z]{3}/;
    	if (sValue.match(sUrl)){
    		return true;
    	}
    	else {
    		if (message) {
                return message;
            }
			return CreatoorSN.common.translate('Invalid url definition. ');
    	}
    	
    },
    
    
    /**
     * Equal to compared string
     * 
     * @method num
     * @param {Object} oValidator
     * @param {string} sValue
     * 
     * @return {boolean|string}
     * @exception Error
     */
    same : function (oValidator, sValue) {
        
        if (YAHOO.lang.isObject(oValidator) === false ||
            YAHOO.lang.hasOwnProperty(oValidator, 'sCompare') === false) {
            throw new Error('Same validator: string for comparisson required in validator object');
        }
        
        if (oValidator.sCompare === sValue) {              
            return true;
        } else {
            if (oValidator.message) {
                return message;
            }
            return CreatoorSN.common.translate('Values are not the same.');
        }               
        
    },
    
    /**
     * Value on specified list
     * 
     * @method inArray
     * @param {object} oValidator
     * @param {string} sValue
     * @return {boolean|string}
     * @exception TypeError
     */
    inArray : function (oValidator, sValue) {

        if (YAHOO.lang.isObject(oValidator) === false) {
            throw new TypeError("InArray Validator -> Value: Expected a String");
        } else if (YAHOO.lang.hasOwnProperty(oValidator, 'oValues') === false ||
                   YAHOO.lang.isArray(oValidator.oValues) === false) {
            throw new Error('InArray -> validator requires array as a parameter');
        }
        
        if (YAHOO.lang.isString(sValue) === false) {
            throw new TypeError("InArray Validator -> Value: Expected a String");
        }

        var i=0,
            iLen = oValidator.oValues.length;
            
        for (i=0; i<iLen; i++) {
            if (oValidator.oValues[i] == sValue) {
                return true;
            }            
        }
        if (oValidator.message) {
            return message;
        }
        return CreatoorSN.common.translate('Value not valid');      
        
    }
    
};
