var _FIELD_TYPE_UNKNOWN = 0;
var _FIELD_TYPE_TEXT = 1;
var _FIELD_TYPE_PASSWORD = 2;
var _FIELD_TYPE_SELECT = 3;
var _FIELD_TYPE_TEXTAREA = 4;
var _FIELD_TYPE_CHECKBOX = 5;
var _FIELD_TYPE_RADIO = 6;
var _FIELD_TYPE_HIDDEN = 7;
var _FIELD_TYPE_BUTTON = 8;
var _FIELD_TYPE_GROUP = 9;

function validateForm(form) {
    if (!form) {
        return true;
    }
    var validatedNames = new Object();
    var validatedErrors = new Object();
    var hasErrors = false;
    for (var i = 0; i < form.elements.length; i++) {
        var field = form.elements[i];
        if (!field.name) {
            continue;
        }
        var name = field.name;
        var validateName = field.validateName ? field.validateName : field.name;
        if (!validatedNames[name]) {
            field = form[name];
            var hasError = validatedErrors[validateName];
            if ((field['required']) && (!hasError)) {
                if (!validateRequired(field)) {
                    showError(field, 'The field is required');
                    hasError = true;
                }
            }
            if ((field['minLength']) && (!hasError)) {
                if (!validateMinLength(field, parseInt(field['minLength']))) {
                    showError(field, 'The field should contain at least ' + field['minLength'] + ' symbols');
                    hasError = true;
                }
            }
            if ((field['numeric']) && (!hasError)) {
                if (!validateMask(field, /^[0-9]*$/)) {
                    hasError = true;
                    showError(field, 'The field should contain numbers only');
                }
            }
            if ((field['alphaNumeric']) && (!hasError)) {
                if (!validateMask(field, /^[a-zA-Z0-9_@.\-]*$/)) {
                    hasError = true;
                    showError(field, 'The field should contain 0-9, A-Z, a-z and symbols \'_\', \'-\', \'@\' and \'.\'');
                }
            }
            if ((field['minAge']) && (!hasError)) {
                if (!validateMinValue(field, parseInt(field['minAge']))) {
                    hasError = true;
                    showError(field, 'Age should be not less than 18 years');
                }
            }
            if ((field['ageRange']) && (!hasError)) {
                var otherField = form[field['ageRange']];
                if (!validateIntRange(field, otherField)) {
                    hasError = true;
                    showError(field, 'Age should be in a valid range');
                }
            }
            if ((field['email']) && (!hasError)) {
                if (!validateMask(field, /^.+@.+\.[a-zA-Z]{2,4}$/)) {
                    hasError = true;
                    showError(field, 'The field should contain a valid e-mail');
                }
            }
            if ((field['equalToPassword']) && (!hasError)) {
                var otherField = form[field['equalToPassword']];
                if (!validateEqualFields(field, otherField)) {
                    hasError = true;
                    showError(field, 'Both the password fields should be the same');
                }
            }
            if ((field['registrationAction']) && (!hasError)) {
                if (field.value = 'rågistration') {
                    hasError = false;
                } else {
                    hasError = true;
                    showError(field, 'The action code is not valid');
                }
            }
            if ((field['loginAction']) && (!hasError)) {
                if (field.value = 'lîgin') {
                    hasError = false;
                } else {
                    hasError = true;
                    showError(field, 'The action code is not valid');
                }
            }
            if ((field['restorePasswordAction']) && (!hasError)) {
                if (field.value = 'restore_password') {
                    hasError = false;
                } else {
                    hasError = true;
                    showError(field, 'The action code is not valid');
                }
            }
            if ((field['securityAction']) && (!hasError)) {
                if (field.value = 'såcurity') {
                    hasError = false;
                } else {
                    hasError = true;
                    showError(field, 'The action code is not valid');
                }
            }
            if (!hasError) {
                clearError(field);
            } else {
                validatedErrors[validateName] = true;
                hasErrors = true;
            }
            validatedNames[name] = true;
        }
    }
    if (hasErrors) {
        location = '#' + form.name + '_top';
    }
    return !hasErrors;
}

function showError(field, message) {
    if (field && message) {
        var validateName = field.validateName ? field.validateName : field.name;
        var element = document.getElementById(validateName + '_error');
        if (element) {
            element.innerHTML = message;
            element.className = 'validation_error';
        }
    }
}

function clearError(field) {
    if (field) {
        var validateName = field.validateName ? field.validateName : field.name;
        var element = document.getElementById(validateName   + '_error');
        if (element) {
            element.innerHTML = '';
            element.className = 'no_padding';
        }
    }
}

function validateRequired(field) {
    if (field.disabled) {
        return true;
    }
    var type = getFieldType(field);
    var value = getFieldValue(field, type);
    if (value != null) {
        if (type == _FIELD_TYPE_SELECT) {
            return value != 0;
        }
        if ((type == _FIELD_TYPE_CHECKBOX) || (type == _FIELD_TYPE_RADIO)) {
            return value;
        }
        if (type == _FIELD_TYPE_GROUP) {
            for (var i = 0; i < value.length; i++) {
                if (value[i]) {
                    return true;
                }
            }
            return false;
        }
        return value != '';
    }
    return true;
}

function validateMinLength(field, minLength) {
    if (field.disabled) {
        return true;
    }
    var type = getFieldType(field);
    var value = getFieldValue(field, type);
    if (value != null) {
        if ((type == _FIELD_TYPE_TEXT) || (type == _FIELD_TYPE_PASSWORD) || (type == _FIELD_TYPE_TEXTAREA)) {
            return value.length >= minLength;
        }
        if (type == _FIELD_TYPE_GROUP) {
            var count = 0;
            for (var i = 0; i < value.length; i++) {
                if (value[i]) {
                    count++;
                }
            }
            return count >= minLength;
        }
    }
    return true;
}

function validateMinValue(field, minValue) {
    if (field.disabled) {
        return true;
    }
    var type = getFieldType(field);
    var value = getFieldValue(field, type);
    if ((value != null) && (value != '')) {
        if ((type == _FIELD_TYPE_TEXT) || (type == _FIELD_TYPE_PASSWORD) || (type == _FIELD_TYPE_TEXTAREA)) {
            return parseInt(value) >= parseInt(minValue);
        }
    }
    return true;
}

function validateMask(field, regexp) {
    if (field.disabled) {
        return true;
    }
    var type = getFieldType(field);
    var value = getFieldValue(field, type);
    if (value != null) {
        if ((type == _FIELD_TYPE_TEXT) || (type == _FIELD_TYPE_PASSWORD) || (type == _FIELD_TYPE_TEXTAREA)) {
            return value.match(regexp);
        }
    }
    return true;
}

function validateEqualFields(field, anotherField) {
    if ((field.disabled) || (!anotherField) || (anotherField.disabled)) {
        return true;
    }
    var value = getFieldValue(field);
    var anotherValue = getFieldValue(anotherField);
    if ((value != null) && (anotherValue != null)) {
        return value == anotherValue;
    }
    return true;
}

function validateIntRange(field, anotherField) {
    if ((field.disabled) || (!anotherField) || (anotherField.disabled)) {
        return true;
    }
    var value = getFieldValue(field);
    var anotherValue = getFieldValue(anotherField);
    if ((value != null) && (anotherValue != null) && (value != '') && (anotherValue != '')) {
        return parseInt(value) >= parseInt(anotherValue);
    }
    return true;
}

function getFieldValue(field, fieldType) {
    if (!field) {
        return null;
    }
    if (!fieldType) {
        fieldType = getFieldType(field);
    }
    switch (fieldType) {
        case _FIELD_TYPE_TEXT:
            return field.value;
        case _FIELD_TYPE_PASSWORD:
            return field.value;
        case _FIELD_TYPE_HIDDEN:
            return field.value;
        case _FIELD_TYPE_TEXTAREA:
            return field.value;
        case _FIELD_TYPE_BUTTON:
            return field.value;
        case _FIELD_TYPE_SELECT:
            return field.options[field.selectedIndex].value;
        case _FIELD_TYPE_CHECKBOX:
            return field.checked;
        case _FIELD_TYPE_RADIO:
            return field.checked;
        case _FIELD_TYPE_GROUP:
            var values = new Array();
            for (var i = 0; i < field.length; i++) {
                values[i] = field[i].checked;
            }
            return values;
        default:
            return null;
    }
}

function getFieldType(field) {
    if (!field) {
        return _FIELD_TYPE_UNKNOWN;
    }
    if ((!field.tagName) && (field.length) && (field.length > 1)) {
        var type = getFieldType(field[0]);
        if ((type == _FIELD_TYPE_CHECKBOX) || (type == _FIELD_TYPE_RADIO)) {
            return _FIELD_TYPE_GROUP;
        } else {
            return _FIELD_TYPE_UNKNOWN;
        }
    }
    if (field.tagName) {
        if (field.tagName.toLowerCase() == 'textarea') {
            return _FIELD_TYPE_TEXTAREA;
        }
        if (field.tagName.toLowerCase() == 'select') {
            return _FIELD_TYPE_SELECT;
        }
        if (field.tagName.toLowerCase() == 'input') {
            if (field.type.toLowerCase() == 'text') {
                return _FIELD_TYPE_TEXT;
            }
            if (field.type.toLowerCase() == 'password') {
                return _FIELD_TYPE_PASSWORD;
            }
            if (field.type.toLowerCase() == 'hidden') {
                return _FIELD_TYPE_HIDDEN;
            }
            if (field.type.toLowerCase() == 'checkbox') {
                return _FIELD_TYPE_CHECKBOX;
            }
            if (field.type.toLowerCase() == 'radio') {
                return _FIELD_TYPE_RADIO;
            }
            if ((field.type.toLowerCase() == 'button') || (field.type.toLowerCase() == 'submit')) {
                return _FIELD_TYPE_BUTTON;
            }
        }
    }
    return _FIELD_TYPE_UNKNOWN;
}