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) 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(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{

			//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;

		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.value == "")
						valid = false;

					if(!valid)
					{                 //TODO add error should clear first
						if(el_parent)
							validator.add_error(el,el_parent,'The Field: "'+validator.get_field_label(el)+'" is Required');
					}
				}
			}
		}

		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);
		});
	}
}