/**
 * Author: Eugene Churmanov <eugenechurmanov@soft-rose.com>
 * Company: Soft-Rose
 * File: formvalidator.js
 * Creation Date: 15.01.2010
 * Modifed: 19.01.2010 12:43
 * Note:
 * Form Validation singilton object for instant validation form based on Zend_Form.
 * !Warning!: Validated form not must contain elements whith id/name "submit" 
 * 
 */
FormValidator = function()
{
	/**
	 * Associative list of Error messages
	 * Temporale solution, until will be not usage Zend_Validator error message 
	 * 
	 */
	var messageList = {
		"isEmpty": "This field is required",
		"emptyValue": "This field is required",
		"emailAddressLengthExceeded": "E-mail exceeds the allowed length",
		"emailAddressInvalidFormat": "Wrong email addres format",
		"emailAddressInvalidHostname": "Hostname is not a valid for email address",
		"TOO_SHORT": "String is too short",
		"TOO_LONG": "String is too long",
		"notMatch": "Entries do not match",
		"weakPassword": "Password should be at least 8 characters long.",
		"emptyPassword": "Please enter password."
	};
	
	/**
	 * Validator NewUserEmail
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
	function NewUserEmail(e,a){
		var v = e.getValue();
		var res = NotEmpty(e,a);
		if (!res.valid){
			return res;
		}
		res = EmailAddress(e,a);
		return res;
	}
	/**
	 * Validator UserPassword
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
	function UserPassword(e,a){
		var v = e.getValue();
        return {
            valid: v.length != 0, 
            code: v.length == 0 ? "emptyPassword" : undefined
        };
	}
	/**
	 * Validator NotEmpty
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
    function NotEmpty(e,a)
    {
        var v = e.getValue();
        return {
            valid: v.length != 0, 
            code: v.length == 0 ? "isEmpty" : undefined
        };
    }
    /**
	 * Validator EmailAddress
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
    function EmailAddress(e,a){
    	var v = e.getValue();
    	if ( v.indexOf('@')>64 || v.length - v.indexOf('@') > 255){
    		return {
    			valid: false,
    			code: "emailAddressLengthExceeded"
    		};
    	}
    	if ( v.indexOf('@') < 1 || v.indexOf('@') != v.lastIndexOf('@') ){
    		return {
    			valid: false,
    			code: "emailAddressInvalidFormat"
    		};
    	}
    	if ( v.indexOf('.', v.indexOf('@')) == -1 || 
    			v.lastIndexOf('.') == v.length-1 || 
    			v.charAt(v.indexOf('@') + 1) == '.' ){
    		return {
    			valid: false,
    			code: "emailAddressInvalidHostname"
    		};
    	}
    	return {
    		valid: true
    	};
    	
    }
    /**
	 * Validator UserEmail
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
    function UserEmail(e,a){
    	var v = e.getValue();
    	if (v.length == 0){
    		return {
    			valid: false,
    			code: "emptyValue"
    		};
    	}
    	
    	if ( v.indexOf('@') < 1 ||
    			v.indexOf('@') != v.lastIndexOf('@') ||
    			v.indexOf('.', v.indexOf('@')) == -1 ||
    			v.lastIndexOf('.') == v.length-1 || 
    			v.charAt(v.indexOf('@') + 1) == '.'
    		){
    		return {
    			valid: false,
    			code: "Invalid E-mail Format"
    		};
    	}
    	return {
    		valid: true
    	};
    }
    /**
	 * Validator StringLength
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
    function StringLength(e,a)
    {
        var v = e.getValue();
        if (v.length <= a[0]) {
            return {
                valid: false, 
                code: "TOO_SHORT"
            };
        }
        if (v.length >= a[1]) {
            return {
                valid: false,
                code: "TOO_LONG"
            };
        }
        return {
            valid: true
        }
    }
    /**
	 * Validator Passwords
	 * @param Object e - element for validation
	 * @param array a - array of params for validator 
	 * @return Object {valid: bool, code: string} - result of validation and error code (if need)
	 */
    function Passwords(e,a)
    {
        var v = e.getValue();
        if (a[0] == null) {
        	var conf=FormValidator.configs;
        	for (var i = 0; i < conf.length; i++){
        		var val=conf[i].validators;
        		for (var j=0; j < val.length; j++){
        			if (val[j].validator == "Passwords" && val[j].params[0] == e.id){
        				checkElementValid(Ext.get(FormValidator.elements[i].id));
        			}
        		}
        	}
            return {
                valid: v.length >= 8, 
                code: v.length < 8 ? "weakPassword" : undefined
            };
        }
        
        if (v == Ext.fly(a[0]).getValue()) {
            return {
                valid: true
            };
        } else {
            return {
                valid: false, 
                code: "notMatch"
            };
        }
    }
    /**
     * function checkElementValidOnEvent
     * Fire on validated element event
     * @param EventObject e 
     * @param HTMLElement t 
     */
    function checkElementValidOnEvent(e,t)
    {
        el = Ext.get(t);
        if (el && Ext.isObject(el)) {
            checkElementValid(el);
        }
    }
    /**
     * function checkElementValid
     * Check all validators of elemen
     * @param Object el - EventObject
     * @return bool - valid or not valid value of element
     */
    function checkElementValid(el){
        var result = true;
        var validator = FormValidator.configs[FormValidator.elements.indexOf(el)].validators;
        var ul = el.next("ul.errors");
        if (ul) {
            ul.remove();
            dd = el.parent();
            ulConfig = {
                tag: "ul",
                cls: "errors",
                html: ""
            };
            ul=dd.createChild(ulConfig);
            ul.insertAfter(el);
        }
        var validing = true;
        for (var i=0,v=validator[i]; i < validator.length && validing  ; i++,v = validator[i]) {
        	try{
	        	var res = eval(v.validator)(el, v.params);
	        	if (!res.valid) {
	        		/**
	        		 *	Temporale disable using message from server validators
	        		 *	replaced by JS messageList
	        		 *	 
	        		 */
	        		if (messageList[res.code]){
	        			var message = messageList[res.code];
	        		} else {
	        			var message = res.code;
	        		}
	        		if (v.messages[res.code]){
	        			var message = v.messages[res.code];
	        		} else {
	        			var message = v.messages;
	        		}
	                
	        		/**
	        		 *	//
	        		 */
	                liConfig = {
	                    tag: "li",
	                    cls: "",
	                    html: message
	                };
	                result = false;
	                el.next("ul.errors").createChild(liConfig);
	            }
            } catch(e) {
            	result = true;
            }
            validing = (result || !v.validStop);
        }
        return result;
    }
    /**
     * validateForm
     * Validate all elements in cofiguration
     * @return bool - valid or not valid form
     */
    function validateForm()
    {
        var result = true;
        for (var y = 0, res; y < FormValidator.elements.length; y++) {
            res = checkElementValid(FormValidator.elements[y]);
            result = result && res;
        }
        return result;
    }
    /**
     * addElementValidation
     * Add configuretion of one element to singilton
     * @param Object config - object of element configuration
     * @return bool - return true if configureation is apply
     */
    function addElementValidation(config){
        if (Ext.isObject(config)) {
        	if (config.type == "SUBMIT"){
        		var sub = Ext.get(config.elementId);
        		sub.on(
        			'click',
        			function (e,t) {
        				var res = validateForm();
                    	if (!res){
                    		e.preventDefault();
                        }
                        return res;
        			}
        		);
        		return true;
        	}
            if (config.elementId && config.validators) {
                if (FormValidator.elements.indexOf(Ext.get(config.elementId)) >= 0){
                    return false;
                }
                var l = FormValidator.elements.length;
                var el = Ext.get(config.elementId);
                
                FormValidator.elements[l] = el;
                FormValidator.configs[l] = config;
                var ul=el.next("ul.errors");
                if (!ul){
                    dd = el.parent();
                    ulConfig = {
                        tag: "ul",
                        cls: "errors",
                        html: ""
                    };
                    ul=dd.createChild(ulConfig);
                    ul.insertAfter(el);
                }
                
                return true;
            }
        }
        return false;
    }
    /**
     * Public part of singilton 
     */
    return {
        /**
         * Array of elements and configs 
         */
        elements: [],
        configs: [],
        /**
         * configure
         * Public method for getting configuration
         * @param array configForm - array of element valid configuration 
         */
        configure: function(configForm)
        {
            if (configForm.length>0) {
                for (var i = 0; i < configForm.length; i++){
                    addElementValidation(configForm[i]);
                    
                }
            }
        },
    	submit: function()
    	{
        	var res = validateForm();
        	if (!res){
        		return false;
            }
            el = Ext.get(this.elements[0]).parent('form');
            el.dom.submit();
        }
        
    };
}();
