var validator = {

    ajax_con:false,
    form:false,
    debug:false,
    php_controler:'/validate/',
    existing_div_class:'required',
    is_valid:true,
    id_prefix:'',
    error_class:'error',
    error_message_div:'errors',
    auto_submit:true,
    error_string:'',
    validation_lock:false,
    param_string:'',



    init:function(){

        validator.ajax_con = new XHConn();
        validator.form = false;
        validator.is_valid = true;
        validator.id_prefix = "";
        validator.arr_form_els = null;

        if (!validator.ajax_con){

            if(validator.debug){
                alert('no XHconn');
            }

        }
    },

    validate_form:function (frm,model_name)
    {
        if(validator.validation_lock) return;

        validator.validation_lock = true;

        if (!validator.ajax_con && model_name) validator.init();

        validator.form = frm;

        validator.is_valid = true;

        //show message will clear this
        validator.disable_submit_button();

        validator.clear_all_errors();

        //do non ajax validation of fields providing there isnt to many of them
        //if(validator.form.elements.length < 100)
        validator.validate_all_el_required(validator.form);

        if(validator.is_valid)
        {
            if(model_name)
            {//do ajax validation

                if(validator.debug) alert('basic validation is ok, now do ajax validation');

                var model_id = validator.get_form_model_id();

                var params = "ajax=t&_model_name="+model_name +"&id="+ model_id + validator.fields_to_params();

                if(validator.debug) alert('ajax params are '+params);

                validator.auto_submit = true;

                validator.ajax_con.connect(validator.php_controler+'model',"POST",params,validator.display_ajax_validation_response);
                return false; //as ajax will submit the form if its ok
            }
            else
            return true;

        }else{

            //Display basic validation (ie empty field errors)
            validator.validation_lock = false;
            validator.show_error_messages();

            return false;
        }
    },

    validate_field:function (el,el_parent)
    {

        if(validator.validation_lock) return;

        validator.validation_lock = true;

        if (!validator.ajax_con) validator.init();

        validator.clear_error_messages();

        validator.form = el.form;

        if(el_parent == null) el_parent = validator.get_field_parent(el);

        //try basic validation
        if(validator.validate_el_required(el,el_parent))
        {
            if(validator.debug)
            alert('basic validation is ok, now do ajax validation');

            var model_name;
            var model_id;

            if(model_name = document.getElementById('model_name').value)
            {
                model_id = validator.get_form_model_id();

                var params = "ajax=t&_model_name="+model_name +"&id="+ model_id + "&field="+el.name+"&value="+el.value;

                if(validator.debug)
                $('#'+validator.error_message_div).append('debug: '+params);

                //we will not submit form
                validator.auto_submit = false;

                validator.ajax_con.connect(validator.php_controler+'field',"POST", params, validator.display_ajax_validation_response);

            }else if(validator.debug)
            {
                /*alert('cant find model_name: '+model_name+' or model_id: '+model_id);*/
                validator.validation_lock = false;
            }
        }else{

            validator.validation_lock = false;
            validator.show_error_messages();//show basic required errors
        }
    },

    // this will be called when ajax request completes
    display_ajax_validation_response: function(oXML)
    {
        validator.is_valid = true;

        try{

            var respText = oXML.responseText;

            if(validator.debug) alert(respText);

            if(respText == 'true')
            {
                validator.ajax_validation_successfull = true;

                //TODO I think this can switch to false sometimes via validate_field when it shouldnt
                if(validator.auto_submit)
                {
                    validator.validation_lock = false;
                    validator.form.submit();

                }
            }
            else
            validator.ajax_validation_successfull = false;

            var respDoc = oXML.responseXML;

            //Clear any ajax errors
            validator.clear_error_messages();

            if(!respDoc){
                validator.validation_lock = false;
                return;
            }

            //firstChild.nodeValue;
            var val_result = respDoc.getElementsByTagName('validate-result').item(0);

            var fields = val_result.getElementsByTagName('field');

            for(var i =0; i<fields.length; i++)
            {
                var el_name = fields.item(i).getElementsByTagName('name').item(0).firstChild.nodeValue;
                var parent_div = document.getElementById('el_'+validator.id_prefix+el_name);
                var el = document.getElementById(validator.id_prefix+el_name);

                var message = fields.item(i).getElementsByTagName('message').item(0).firstChild.nodeValue;

                //this fields is invalid and we need to say why');
                validator.add_error(el,parent_div, message);
            }
        }
        catch(e)
        {
            validator.ajax_validation_successfull = false;
            validator.enable_submit_button();
            validator.validation_lock = false;
        }

        validator.validation_lock = false;
        validator.enable_submit_button();

        //If we had any errors, display them
        if(!validator.ajax_validation_successfull)
        validator.show_error_messages();
    },

    get_field_parent:function(el)
    {
        return $(el).parents('li').get(0);
    },

    disable_submit_button:function(){

        try{
            validator.form.submit_validate.disabled = true;
        }catch(e){}
    },

    enable_submit_button:function(){

        try{
            validator.form.submit_validate.disabled = false;
        }catch(e){}
    },

    validate_el_required: function(el,el_parent)
    {
        var valid = true;
        var html_editor_iframe = null;
        var message = null;

        if((el.type != 'checkbox' && el.type != 'hidden' && el.style.display != 'none') && (el.nodeName == 'INPUT' || el.nodeName == 'TEXTAREA' ||  el.nodeName == 'SELECT'))
        {
            if(!el_parent)
            el_parent = validator.get_field_parent(el);

            if(el_parent)
            {
                if(el_parent.className == 'required' || el_parent.className==validator.error_class)
                {
                    if(el.type == 'radio' && !validator.is_radio_button_selected(el.name)){

                        valid = false;
                        message = 'Please select <b>'+validator.humanize(el.name)+'</b>';

                    }
                    else if(el.value == ""){
                        valid = false;
                        message = 'The Field: "'+validator.get_field_label(el)+'" is Required';
                    }

                    if(!valid)
                    {                 //TODO add error should clear first
                        if(el_parent)
                        validator.add_error(el,el_parent,message);
                    }
                }
            }
        }
        return valid;
    },

    validate_all_el_required: function(element)
    {
        if(!element)
        element = validator.form;

        validator.is_valid = true;

        $(validator.get_arr_form_elements(element)).each(function()
        {
            if(!validator.validate_el_required(this))
            validator.is_valid = false;
        });

        return validator.is_valid;
    },

    get_arr_form_elements: function(element)
    {
        //if(!validator.arr_form_els[element])
        validator.arr_form_els = $('input, select, textarea', element);

        return validator.arr_form_els;
    },

    add_error: function (el,el_parent,message)
    {
        if(el_parent)
        $(el_parent).find('input, textarea, select').addClass(validator.error_class); //Signal a required field

        if(el)
        message = '<a href="#' + el.id + '">'+message+'</a>';

        validator.error_string += '<li>'+message+'</li>';

        validator.is_valid = false;
    },

    clear_error: function(el_parent)
    {
        $(el_parent).find('input, textarea, select').removeClass(validator.error_class);
    },

    clear_all_errors: function()
    {
        $(validator.form).find('li').each(function(i){
            validator.clear_error(this);
        });

        validator.clear_error_messages();
    },

    //shows then clears messages
    show_error_messages: function()
    {
        if(validator.error_string != '')
        $('#' + validator.error_message_div).append('<ul class="errorList">' + validator.error_string + '</ul>');

        validator.error_string = '';

        validator.enable_submit_button();

        document.location = '#' + validator.error_message_div;
    },

    clear_error_messages: function()
    {
        validator.error_string = '';
        $('#'+validator.error_message_div).html('');
    },

    fields_to_params: function()
    {
        param_string  = "";

        var getparam = function(el)
        {
            var name = el.name;
            var bracket_index = name.indexOf('[');

            if(bracket_index > 0)
            {
                validator.id_prefix = name.substring(0,bracket_index);

                //look for html array syntax, if we have it get the content between brakets
                var inner_name = name.substring(bracket_index+1,name.indexOf(']'));

                //dont bother with numerically indexed jazzed
                //if(!parseInt(inner_name))
                name = inner_name;

                // validator.id_prefix allows us to reference the valid id for an html array element,
                // eg shipping[first_name]
                //
                // name = first_name
                // validator.setformat = shipping
                //
                // so Id should be shippingname
            }

            param_string += "&" + name + "=" + el.value;
        }

        $(validator.get_arr_form_elements(validator.form)).each(function ()
        {
            if(this.type != 'hidden' && this.type != 'checkbox' && this.style.display !='none')
            getparam(this);
        });

        return param_string;
    },

    get_form_model_id: function ()
    {
        var model_id = false;

        try{
            model_id = validator.form.id.value;
        }
        catch(e){
            validator.form.enable_submit_button();
        }

        return model_id;
    },

    get_field_label: function(el)
    {

        parent_li_element = validator.get_field_parent(el);

        label_text = $('label',parent_li_element).text();

        label_text_without_star = label_text.replace('*','');

        return label_text_without_star;
    },

    /**
    * Experimental use with caution
    * Dont forget to add onblur = null to objects that you dont want this to happen to, ie submit button
    */
    attach_validate_field_to_all:function(frm)
    {
        validator.form = frm;

        $(frm).find('input, textarea, select').bind('blur',function(){
            validator.validate_field(this);
        });
    },

    is_radio_button_selected: function(radio_name)
    {
        var elements = document.getElementsByName(radio_name);
        for(var i=0, element; element = elements[i]; i++) {
            if(element.checked) {
                return true;
            }
        }
        return false;
    },

    humanize: function(text){

        text = text.replace(/-|_/g,' ');

        return text.toLowerCase().replace(/\w+/g,function(s){
        return s.charAt(0).toUpperCase() + s.substr(1);
    })
}
}