/**
 * 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();
        }
        
    };
}();
