/*
 * The instance 'rhzJs' is used for accessing members of 'RHZJSObject' 
 */
var rhzUtil = new RHZUtilJSObject();
/* 
 * RHZJS Object for encapsulating methods required by RHZ web 
 */
function RHZUtilJSObject() {
    this.ajaxObj = rhzjs_getAJAXObject();
    this.getAJAXObject = rhzjs_getAJAXObject;
    this.prepareRHZRequestURL = rhzjs_prepareRHZRequestURL;
    this.ajaxCall = rhzjs_ajaxCall;
    this.getModelChildren = rhzjs_getModelChildren;
    this.getChildModelById = rhzjs_getChildModelById;
    this.getModelById = rhzjs_getModelById;
    this.getChildModelParam = rhzjs_getChildModelParam;
    this.getModelParams = rhzjs_getModelParams;
    this.getModelParam = rhzjs_getModelParam;
    this.getParam = rhzjs_getParam;
    this.setParam = rhzjs_setParam;
    this.buildFormParams = rhzjs_buildFormParams;
    this.isEmpty = rhzjs_isEmpty;
    this.checkRequired = rhzjs_checkRequired;
    this.getCookie = rhzjs_getCookie;
    this.checkUserName = rhzjs_checkUserName;
    this.checkPassword = rhzjs_checkPassword;
    this.checkPhone = rhzjs_checkPhone;
    this.removeEmChildren = rhzjs_removeEmChildren;
    this.getChildById = rhzjs_getChildById;
}

/*
 * Conventional method for getting an instance of AJAX object for
 * various browsers:  Firefox, Opera 8.0+, Safari, Internet Explorer
 */
function rhzjs_getAJAXObject() {
    var xmlHttp;
    try {
        // Firefox, Opera 8.0+, Safari
        xmlHttp = new XMLHttpRequest();
    } catch (e) {
        // Internet Explorer
        try {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                alert("Your browser does not support AJAX!");
                return false;
            }
        }
    }
    return xmlHttp;
}

/*
 * Call RHZServletContainer using AJAX object
 *
 * @param serviceId Id of service to invoke
 * @param processId Id of process ti invoke
 * @param flowId Id of flow to invoke
 * @param requestCatalogId Id of catalog for getting request/response binder component
 * @param requestId Id of request/response binder component
 */
function rhzjs_ajaxCall(serviceId, processId, flowId, requestCatalogId, requestId, handlerMethod, formId) {
    if (rhzJs.ajaxObj == null) return;
    rhzJs.ajaxObj.onreadystatechange = handlerMethod;
    var url = rhzjs_prepareRHZRequestURL(serviceId, processId, flowId, requestCatalogId, requestId, formId);

    //The purpose of this line is change the URL for every call in order to prevent AJAX call from returning cached page
    url = url.concat("noCache=", (new Date).getTime(), ".", Math.random() * 1234567);
    rhzJs.ajaxObj.open("GET", url, true);
    rhzJs.ajaxObj.send(null);
    return true;
}


/*
 * Prepare conventinoal request to 'RHZServletContainer' that contains the four required
 * params.
 * @param serviceId Id of service to invoke
 * @param processId Id of process ti invoke
 * @param flowId Id of flow to invoke
 * @param requestCatalogId Id of catalog for getting request/response binder component
 * @param requestId Id of request/response binder component
 * @param formId Id of form whom imputs we would like to use for building form's params String
 */
function rhzjs_prepareRHZRequestURL(serviceId, processId, flowId, requestCatalogId, requestId, formId) {
    var formParams;


    var params = "service-id=" + serviceId
            + "&process-id=" + processId
            + "&flow-id=" + flowId
            + "&request-catalog-id=" + requestCatalogId
            + "&request-id=" + requestId ;
    if (formId != null) {
        formParams = rhzjs_buildFormParams(formId);
        params += "&" + formParams;
    }
    return "servlet/RHZServletContainer?" + params;
}

/**
 * Conventional method for getting NodsList of RHZBean-like elements from 'parenXmlEm'
 * @param parenXmlEm
 */
function rhzjs_getModelChildren(parenXmlEm) {
    var arr = new Array();
    var nlist = parenXmlEm.childNodes;
    for (var i = 0; i < nlist.length; i++) {
        if (nlist[i].nodeName == "RHZBean") {
            arr.push(nlist[i]);
        }
    }

    return arr;
}

/**
 * Conventional method for getting NodsList of 'param' elements from RHZBean-like model 'parenXmlEm'
 * @param parenXmlEm
 */
function rhzjs_getModelParams(parenXmlEm) {
    var arr = new Array();
    var nlist = parenXmlEm.childNodes;
    for (var i = 0; i < nlist.length; i++) {
        if (nlist[i].nodeName == "param") {
            arr.push(nlist[i]);
        }
    }

    return arr;
}

/*
 * Get RHZBean-like model with the specified 'modelId'
 *
 * @param modelId    the Id of model to return
 * @return the child bean with the specified Id
 * @throws rhz.RHZRuntimeException if error occured in case of internal cloning
 */
function rhzjs_getChildModelById(xmlEm, modelId) {

    var nodes = rhzjs_getModelChildren(xmlEm);
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].getAttribute("id") == modelId) {
            return nodes[i];
        }
    }
    return null;
}

/**
 * Get RHZBean-like model by Id
 *
 * @param xmlEm RHZBean-like parent model
 * @param modelId If of sub model to retive
 */
function rhzjs_getModelById(xmlEm, modelId) {
    //search level
    var nodes = xmlEm.getElementsByTagName("RHZBean");
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].tagName == "RHZBean" && nodes[i].getAttribute("id") == modelId) {
            return nodes[i];
        }
    }

    for (var c = 0; i < nodes.length; c++) {
        if (nodes[i].tagName == "RHZBean") {
            var rc = rhzjs_getModelById(nodes[i], modelId);
            if (rc != null) {
                return rc;
            }
        }
    }
    return null;
}


/*
 * Get the value of param 'paramName' for RHZBean-like model with Id eqauls to 'modelId'
 *
 * @param xmlEm
 * @param modelId
 * @param paramName
 */
function rhzjs_getChildModelParam(xmlEm, modelId, paramName) {
    var modelXml = rhzjs_getChildModelById(xmlEm, modelId);
    if (modelXml != null) {
        return rhzjs_getParam(modelXml, paramName);
    }
    return null;
}

/*
 * Get the value of param 'paramName' for RHZBean-like model with Id eqauls to 'modelId'
 *
 * @param xmlEm
 * @param modelId
 * @param paramName
 */
function rhzjs_getModelParam(xmlEm, modelId, paramName) {
    var modelXml = rhzjs_getModelById(xmlEm, modelId);
    if (modelXml != null) {
        return rhzjs_getParam(modelXml, paramName);
    }
    return null;
}


/*
 * Get the value of param with name equals to 'paramName' of RHZBean-like model
 * specified by 'modelXml'
 *
 * @param modelXml XML structure that represent RHZBean model
 * @param paramName name of parameter for getting he value from
 */
function rhzjs_getParam(modelXml, paramName) {
    var nodes = rhzjs_getModelParams(modelXml);
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].getAttribute("name") == paramName) {
            var paramNode = nodes[i];
            var val = paramNode.getAttribute("value");
            if (val == null || typeof val == "undefined" || val.length == 0) {
                var nlist = paramNode.childNodes;
                if (typeof nlist != "undefined") {
                    for (var n = 0; n < nlist.length; n++) {
                        if (nlist[n].nodeType == 4) {
                            //nodeType == 4 means CDATA section
                            return nlist[n].data;
                        }
                    }
                }
            }
            return val;
        }
    }
    return null;
}

/**
 * Set the value of param 'paramName' in RHZBean-like model represented by 'modelXml'
 * @param modelXml  model element
 * @param paramName param name
 * @param paramValue param value
 */
function rhzjs_setParam(modelXml, paramName, paramValue) {
    var nodes = rhzjs_getModelParams(modelXml);
    for (var i = 0; i < nodes.length; i++) {
        if (nodes[i].getAttribute("name") == paramName) {
            var paramNode = nodes[i];
            var val = paramNode.getAttribute("value");
            if (val == null || typeof val == "undefined" || val.length == 0) {
                var nlist = paramNode.childNodes;
                if (typeof nlist != "undefined") {
                    for (var n = 0; n < nlist.length; n++) {
                        if (nlist[n].nodeType == 4) {
                            //nodeType == 4 means CDATA section
                            nlist[n].data = paramValue;
                        }
                    }
                }
            } else {
                paramNode.setAttribute("value", paramValue);
            }
            return val;
        }
    }
    return null;
}
/*
 * Iterate all the input fileds of a form with specified 'formId'
 * and buildparams String of those fileds.
 * @param formId
 */
function rhzjs_buildFormParams(formId) {
    var result = "";
    var form = document.getElementById(formId);
    var nodes = form.getElementsByTagName("input");
    for (var i = 0; i < nodes.length; i++) {
        var idVal = nodes[i].id;
        if (rhzjs_isEmpty(idVal)) {
            idVal = nodes[i].name;
        }
        if (rhzjs_isEmpty(idVal)) {
            idVal = nodes[i].name;
        }
        if (! rhzjs_isEmpty(idVal)) {
            result += idVal + "=" + nodes[i].value + "&";
        }
    }
    return result;
}

/*
 * Check if String is empty. A string is considered as empty if itis 'null'
 * or that is'undefined' or it as lenght==0
 * @param str
 */
function rhzjs_isEmpty(str) {
    return str == null || str == undefined || str.length == 0;
}

/*
 * Check list of required fileds, specified within 'fieldsNames' array. Fields are searched
 * using 'document.getElementById(fieldsNames[i])' syntax.
 * If some fields are not set method shows an alert with request for setting the missing fields.
 */
function rhzjs_checkRequired(fieldsNames) {
    var arrInvalid = new Array();
    var index = 0;
    var i = 0;
    for (i = 0; i < fieldsNames.length; i++) {
        if (rhzjs_isEmpty(document.getElementById(fieldsNames[i]).value)) {
            arrInvalid[index++] = fieldsNames[i];
        }
    }
    if (arrInvalid.length > 0) {
        var msg = "Please set the following missing fields:\n\n";
        for (i = 0; i < arrInvalid.length; i++) {
            msg += (i + 1) + ") " + arrInvalid[i] + "\n";
        }
        alert(msg)
        return false;
    }
    return true;
}

/*
 * Check that Username is:
 * 1) not null or empty
 * 2) contain only letters, numbers and underscores
 *
 * @param userName name to check
 */
function rhzjs_checkUserName(userName) {
    if (userName == null || userName == undefined || userName.length < 5) {
        alert("Error: 'User Name' must contain at least 5 characters");
        return false;
    }
    var re = /^\w+$/;
    if (!re.test(userName)) {
        alert("Error: 'User Name' must contain only letters, numbers and underscores!");
        return false;
    }

    return true;
}

/*
 * Check the password:
 * 1) password1 equals password2
 * 2) does not equals to Username
 * 3) contains at least one number
 * 4) contains at lease lower-case letter
 * 5) contains at lease upper-case letter
 *
 *
 * @param password1
 * @param password2
 */
function rhzjs_checkPassword(password1, password2, userName) {
    if (password1 != "" && password1 == password2) {
        if (password1.length < 6) {
            alert("Error: Password must contain at least six characters!");
            return false;
        }
        if (password1 == userName) {
            alert("Error: Password must be different from 'User Name'!");
            return false;
        }
        var re = /[0-9]/;
        if (!re.test(password1)) {
            alert("Error: password must contain at least one number (0-9)!");
            return false;
        }
        re = /[a-z]/;
        if (!re.test(password1)) {
            alert("Error: password must contain at least one lowercase letter (a-z)!");
            return false;
        }
        re = /[A-Z]/;
        if (!re.test(password1)) {
            alert("Error: password must contain at least one uppercase letter (A-Z)!");
            return false;
        }
    } else {
        alert("Error: Please check that you've entered and confirmed your password!");
        return false;
    }
    return true;

}
/*
 * Check the phone number
 * 1) Check that 'country' , 'area' and 'number' are all set
 * 2) Check that all parts contains only numbers
 * @param country country code
 * @param area area code
 * @param number number
 * @param ext extension
 */
function rhzjs_checkPhone(number) {
    if (isEmpty(number)) return true;

    var re = /^\d+$/;
    if (!re.test(number)) {
        alert("Error: 'Phone's number' must contain only numbers!");
        return false;
    }
    return true;
}


function rhzjs_getCookie(c_name) {
    var c_start;
    var c_end;
    var ck = document.cookie;
    if (ck.length > 0) {
        c_start = ck.indexOf(c_name + "=");
        if (c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = ck.indexOf(";", c_start);
            if (c_end == -1) c_end = ck.length;
            return unescape(ck.substring(c_start, c_end));
        }
    }
    return "";
}


function isEmpty(val) {
    return val == null || val == undefined || val.length == 0;
}


/**
 * This method translate back from entities representation to charactres.
 * This actually do the oposite for method {@link #encodeXmlEntities(String)}
 *
 * @param string
 * @return edcoded XML tring
 */
function decodeXmlEntities(string) {
    if (string == null) {
        return null;
    }

    var len = string.length;
    var sb = "";
    for (var i = 0; i < len; i++) {
        var c = string.charAt(i);
        if (c == '&') {
            if (i <= len - 5 && string.charAt(i + 1) == 'a' && string.charAt(i + 2) == 'm' && string.charAt(i + 3) == 'p' && string.charAt(i + 4) == ';') {
                // &amp;
                sb += '&';
                i += 4;
            } else if (i <= len - 4 && string.charAt(i + 1) == 'l' && string.charAt(i + 2) == 't' && string.charAt(i + 3) == ';') {
                // &lt;
                sb += '<';
                i += 3;
            } else if (i <= len - 4 && string.charAt(i + 1) == 'g' && string.charAt(i + 2) == 't' && string.charAt(i + 3) == ';') {
                // &gt;
                sb += '>';
                i += 3;
            } else
                if (i <= len - 6 && string.charAt(i + 1) == 'a' && string.charAt(i + 2) == 'p' && string.charAt(i + 3) == 'o' && string.charAt(i + 4) == 's' && string.charAt(i + 5) == ';') {
                    // &apos;
                    sb += '\'';
                    i += 5;
                } else
                    if (i <= len - 6 && string.charAt(i + 1) == 'q' && string.charAt(i + 2) == 'u' && string.charAt(i + 3) == 'o' && string.charAt(i + 4) == 't' && string.charAt(i + 5) == ';') {
                        // &quot;
                        sb += '"';
                        i += 5;
                    } else {
                        sb += c;
                    }
        } else {
            sb += c;
        }
    }
    return sb.toString();
}

/**
 * Remove all teh children of 'xmlEm'
 * @param xmlEm the element for whom we would like to remove children
 */
function rhzjs_removeEmChildren(xmlEm) {
    if (xmlEm.hasChildNodes()) {
        var len = xmlEm.childNodes.length;
        if (len > 0) {
            for (var i = len - 1; i >= 0; i--) {
                xmlEm.removeChild(xmlEm.childNodes[i]);
            }
        }
    }
}

/**
 * Get child element with the specified Id
 * @param xmlEm parent element
 * @param childId child Id
 */
function rhzjs_getChildById(xmlEm, childId) {
    if (xmlEm.hasChildNodes()) {
        var len = xmlEm.childNodes.length;
        if (len > 0) {
            for (var i = len - 1; i >= 0; i--) {
                var child = xmlEm.childNodes[i];
                if (child.id == childId) return child;
            }
        }
    }
    return null;
}

/**
 * Get window width
 */
function getWindowWidth() {
    var myWidth = 0;
    if (typeof( window.innerWidth ) == 'number') {
        //Non-IE
        myWidth = window.innerWidth;
    } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {
        //IE 6+ in 'standards compliant mode'
        myWidth = document.documentElement.clientWidth;
    } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) {
        //IE 4 compatible
        myWidth = document.body.clientWidth;
    }
    return myWidth;
}

/**
 * Get window height
 */
function getWindowHeight() {
    var myHeight = 0;
    if (typeof( window.innerWidth ) == 'number') {
        //Non-IE
        myHeight = window.innerHeight;
    } else if (document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight )) {
        //IE 6+ in 'standards compliant mode'
        myHeight = document.documentElement.clientHeight;
    } else if (document.body && ( document.body.clientWidth || document.body.clientHeight )) {
        //IE 4 compatible
        myHeight = document.body.clientHeight;
    }
    return myHeight;
}




