JSLIB.namespace("JSLIB.form");
JSLIB.form = {
    // constant for validate()
    DISPLAYERR_ALERTSINGLE: 0,
    DISPLAYERR_ALERTGROUP: 1,
    DISPLAYERR_DISPLAYBLOCK: 2,
    // used by validate() method
    parentObj : null,
    elements : null,
	// fourth element specify the focus element on error
    handleError : function(elem, msg, parts) {
        var name = null;
        if (elem && elem.getAttribute) {
            name = elem.getAttribute("alt_name");
            if (!name) {
                name = elem.getAttribute("name");
            }
        }
        if (typeof(parts) != "object" || parts == null) {
            parts = {};
        }
        parts['fieldname'] = name;
        var key;
        var str = new String(msg);
        for (key in parts) {
            str=str.replace("%"+key+"%", parts[key]);
        }
        return {code:false, emsg:str, focusElement:arguments[3]};
    },
    fetchElements : function(parentObj) {
        // check arguments
        if (!parentObj || !parentObj.getElementsByTagName) {
            return null;
        }        
        // fetch all elements
        var elements = {};
        var parts,parts1,parts2,parts3;
        var i;
        parts1 = parentObj.getElementsByTagName("input");
        parts2 = parentObj.getElementsByTagName("select");
        parts3 = parentObj.getElementsByTagName("textarea");
        parts=[];
        for (i = 0; i < parts1.length; i ++)parts[parts.length] = parts1[i];
        for (i = 0; i < parts2.length; i ++)parts[parts.length] = parts2[i];
        for (i = 0; i < parts3.length; i ++)parts[parts.length] = parts3[i];
        for (i = 0; i < parts.length; i ++) {
            if (parts[i].name) {
                if (typeof(elements[parts[i].name]) == "undefined") {
                    elements[parts[i].name] = parts[i];
                }
                else if (!JSLIB.util.isArray(elements[parts[i].name])) {
                    elements[parts[i].name] = [elements[parts[i].name], parts[i]];
                }
                else {
                    elements[parts[i].name][elements[parts[i].name].length] = parts[i];
                }
            }
			else {
				if (typeof elements["_no_name_"] == "undefined") {
					elements["_no_name_"] = [];
				}
				elements["_no_name_"][elements["_no_name_"].length] = parts[i];
			}
        }
        return elements;
    },
    // parentObj is an DOM object that is the parent of form elements
    // it is not necessary to be a form object (in case of form within form case)
    validate : function(parentObj, displayErrorStyle) {
        // check arguments
        if (!parentObj) {
            return;
        }        
        var elements = this.fetchElements(parentObj);
        this.parentObj = parentObj;
        this.elements = elements;
        var msg = "";
        var allTestOk = true;
        var firstErrObj = null;
		// convert elements array to an easier to use format
		var elements2 = [];
		
        for (var key in elements) {
            var elem = elements[key]; // elem may be array or a form element
			if (JSLIB.util.isFunction(elem)) {
				continue;
			}
			
			if (key == "_no_name_") {
				continue;
			}
			
			elements2[elements2.length] = elem;
		}
		
		if (typeof elements["_no_name_"] != "undefined") {
			for (var i = 0; i < elements["_no_name_"].length; i ++) {
				elements2[elements2.length] = elements["_no_name_"][i];
			}
		}
		
        for (var i = 0; i < elements2.length; i ++) {
            var elem = elements2[i]; // elem may be array or a form element
            var realElem = JSLIB.util.isArray(elem)?elem[0]:elem; // realElem points to the elem or first item in elem if it is an array
            
            // alt attr exists for checking?
            var attr = realElem.getAttribute("alt");
            if (!attr) continue;

            // extract parameters
            var params = attr.split("|");
            var validationType = params[0];
            // if elem is an array, validation type must be either radio or checkbox
            if (JSLIB.util.isArray(elem)&&validationType!="radio"&&validationType!="checkbox") {
                continue;
            }
                        
            var bok = (params[params.length - 1] == "bok");
            var result = {success:true};
            switch (validationType) {
            case "blank": result = this.validateBlank(elem); break;
            case "email": result = this.validateEmail(elem, bok); break;
            case "checkbox": result = this.validateCheckbox(elem, params[1], params[2]); break;
            case "radio": result = this.validateRadio(elem); break;
            case "select": result = this.validateSelect(elem); break;
            case "length": result = this.validateLength(elem, params[1], params[2]); break;
			case "allornone": result = this.validateAllOrNone(elem, params[1], params[2]); break;
            }
            if (!result.success) {
                allTestOk = false;
                var emsg = realElem.getAttribute("emsg");
                if(!emsg&&result.emsg) {
                    emsg=result.emsg;
                }
                if(!emsg){
                    emsg="Error in field '" + realElem.name + "'.";
                }
                if(msg.length > 0) {
                    msg+="\n";
                }
                msg+=emsg;
                switch (displayErrorStyle) {
                case this.DISPLAYERR_ALERTSINGLE:
                    alert(msg);
                    realElem.focus();
                    if (realElem.select) {
                        realElem.select();
                    }
                    return false;
                case this.DISPLAYERR_DISPLAYBLOCK:
                    if (realElem.getAttribute("emsgid")) {
                        var obj = document.getElementById(realElem.getAttribute("emsgid"));
                        if (obj) {
                            obj.style.display = "block";
                        }
                    }
                    // fallthru
                case this.DISPLAYERR_ALERTGROUP:
                default:
                    if (!firstErrObj) {
                        firstErrObj=realElem;
                    }
                    break;
                }
            }
            else {
                switch (displayErrorStyle) {
                case this.DISPLAYERR_DISPLAYBLOCK:
                    if (realElem.getAttribute("emsgid")) {
                        var obj = document.getElementById(realElem.getAttribute("emsgid"));
                        if (obj) {
                            obj.style.display = "none";
                        }
                    }
                    break;
                }
            }
        }
        if (!allTestOk) {
            switch (displayErrorStyle) {
            case this.DISPLAYERR_ALERTGROUP:
            case this.DISPLAYERR_ALERTSINGLE:
                alert(msg);
                firstErrObj.focus();
                if(firstErrObj.select)firstErrObj.select();
                break;
            }
        }
        return allTestOk;
    },
        validateBlank : function(elem) {
        if (typeof(elem.value) != "undefined") {
            if (elem.value.length == 0) {
                return this.handleError(elem, JSLIB.formMsg.MSG_FILLINBLANK, null);
            }
            else {
                return {success:true};
            }
        }
        else {
            return {success:true};
        }
    },
    
    validateEmail : function(elem, bok) {
        if (typeof(elem.value) != "undefined") {
            var s=JSLIB.util.trim(elem.value);
            if (s.length==0&&bok) {
                return {success:true};
            }
            var emailStr=elem.value;
            var emailReg1=/(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; // not valid
            var emailReg2=/^[a-zA-Z0-9\_\-\.]+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,6}|[0-9]{1,3})(\]?)$/; // valid
            if (!(!emailReg1.test(emailStr) && emailReg2.test(emailStr))) {// if syntax is valid
                return this.handleError(elem, JSLIB.formMsg.MSG_CORRECTEMAIL, null);
            }
        }
        return {success:true};
    },
    validateRadio : function(elem) {
        if (!JSLIB.util.isArray(elem)) {
            if (elem.checked) {
                return {success:true};
            }
            return this.handleError(elem, JSLIB.formMsg.MSG_RADIO, null);
        }
        else {
            for(var i=0; i<elem.length; i ++){
                if(elem[i].checked) {
                    return {success:true};
                }
            }            
            return this.handleError(elem[0], JSLIB.formMsg.MSG_RADIO, null);
        }
    },
    validateCheckbox : function(elem, min, max) {
        if (!JSLIB.util.isArray(elem)) {
            if (!elem.checked) {
                return this.handleError(elem, JSLIB.formMsg.MSG_CHECKBOX, null);
            }
        }
        else {
            var numChecked = 0;
            for(var i=0; i<elem.length; i ++){
                if(elem[i].checked)numChecked++;
            }
            if(typeof(min)!="undefined"){
                if (numChecked<min) {
                    if(typeof(max)=="undefined"){
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMIN, {min:min});
                    }
                    else if (min == max) {
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMINMAXSAME, {min:min,max:max});
                    }
                    else {
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMINMAX, {min:min,max:max});
                    }
                }
            }
            if(typeof(max)!="undefined"){
                if(numChecked>max){
                    if(typeof(min)=="undefined"||min==0){
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMAX, {max:max});
                    }
                    else if (min == max) {
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMINMAXSAME, {min:min,max:max});
                    }
                    else {
                        return this.handleError(elem[0], JSLIB.formMsg.MSG_CHECKBOXMINMAX, {min:min,max:max});
                    }
                }
            }
        }
        return {success:true};
    },
    validateSelect : function(elem) {
        if (elem.selectedIndex < 1) {
            return this.handleError(elem, JSLIB.formMsg.MSG_RADIO, null);
        }
        return {success:true};
    },
    validateLength : function(elem, minLength, maxLength) {
        if (typeof elem.value != "undefined") {
            if (typeof minLength != "undefined" && typeof maxLength != "undefined" && minLength != "" && maxLength != "") {
                if (elem.value.length < minLength || elem.value.length > maxLength) {
                    return this.handleError(elem, JSLIB.formUtilsMsg.MSG_LENGTHMINMAX, {min:minLength,max:maxLength});
                }
            }
            if (typeof minLength != "undefined") {
                if (elem.value.length < minLength) {
                    return this.handleError(elem, JSLIB.formUtilsMsg.MSG_LENGTHMIN, {min:minLength});
                }
            }
            if (typeof maxLength != "undefined") {
                if (elem.value.length > maxLength) {
                    return this.handleError(elem, JSLIB.formUtilsMsg.MSG_LENGTHMAX, {max:maxLength});
                }
            }
        }
        return {success:true};
    },

	validateAllOrNone : function (elem, delimiter, fieldnames) {
		var fields = fieldnames.split(delimiter);
		if (fields.length == 0) {
			return {success:true};
		}
		var hasValue = this.elements[fields[0]].value.length > 0;
		for (var i = 1; i < fields.length; i ++) {
			if ((this.elements[fields[i]].value.length > 0) !== hasValue) {
				return this.handleError(elem, JSLIB.formUtilsMsg.MSG_ALLORNONE, {}, this.elements[fields[0]]);
			}
		}
		return {success:true};
	},
    // url - url only without args
    // args - object contains key -> value pair
    xsRequest : function (url, args) {
        if (typeof(args) == "undefined" || args == null) {
            args = {};
        }
        var now = new Date()
        var str = "cb="+encodeURIComponent(now.getTime()); // cache buster
        var key;
        for (key in args) {
			if (key == "_no_name_") {
				continue;
			}
            if (JSLIB.util.isArray(args[key])) {
                for (var i = 0; i < args[key].length; i ++) {
                    if (args[key][i].type == "radio" || args[key][i].type == "checkbox") {
                        if (args[key][i].checked) {
                            value = args[key][i].value;
                            if (!value) value = "on";
                            str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(value);
                        }
                    }
                    else {
                        str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(args[key][i].value);
                    }
                }
            }
            else {
                if (args[key].type == "radio" || args[key].type == "checkbox") {
                    if (args[key].checked) {
                        value = args[key].value;
                        if (!value) value = "on";
                        str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(value);
                    }
                }
                else {
                    str += "&" + encodeURIComponent(key) + "=" + encodeURIComponent(args[key].value);
                }
            }            
        }
        url = url + "?" + str;
        // for debugging
        //alert(url);
        //location.href=url;return;
        var newScriptTag = document.createElement("script");
        newScriptTag.src = url;
        document.body.appendChild(newScriptTag);
    },
    xsSubmit : function (url, parentObj) {
        var elements = this.fetchElements(parentObj);
        this.xsRequest(url, elements);
    }
};
