Event.observe(document, 'dom:loaded', function(){
  show_hide_validation();
  
  // standard form handler is attached to all forms with a class of stdform
  $$('.form-std').each(function(frm){
    attachFormManager(frm);
  });
});

function show_hide_validation() {
  // hide validators with nothing in
  $$('.validation').each(function(validation){
    var errs = validation.select('.val-err');
    var vis = errs.any(function(err) { return err.visible(); });
    if (vis)
      validation.show();
    else
      validation.hide();
  });
}

function attachFormManager(frm) {
  if (!frm.hasClassName('form-self-manage')) {
    // use ajax to send the form?
    if (frm.hasClassName('form-ajax')) {
	    ajaxOnSubmitEvent(frm);
    } else {
	    standardOnSubmitEvent(frm);
    }
  }
}

// standard on submit function used 
function standardOnSubmitEvent(frm) {
  frm = $(frm);

	frm.onsubmit = function() {
		// do all the validation
    if (!form_presubmit_ok(frm)) {
      // something's not happy to continue for some reason - stop the form submission
		  return false;
    }
		
		// otherwise we just let it slip through to a normal submit
		return true;
	};
}


// submit the form using ajax request
function ajaxOnSubmitEvent(frm) {
  frm = $(frm);
  
	Event.observe(frm, 'submit', function(e) {
		// stop the normal submit
		Event.stop(e);

		// is everything ok with the fields
		if (form_presubmit_ok(frm)) {
      // is this a form only for use by logged in members?
      if (frm.hasClassName('form-login-required') && !logged_in()) {
        // throw-up the login form
        request_login( function(){ finishAjaxSubmit(frm); } );
      } else {
        // we can drop straight into the submit now
        finishAjaxSubmit(frm);
      }
		}
	});
};

function finishAjaxSubmit(frm) {
  frm = $(frm);

  var params = Form.serialize(frm);

  // do the async submit
  var request = new Ajax.Request(frm.action,
  {
    asynchronous  : true, 
    parameters    : params, 
    onSuccess     : function(t) { window[frm.name+'_onSuccess'](t, frm); },
    onFailure     : function(t) { window[frm.name+'_onFailure'](t, frm); }
  });
}


function clear_errors() {
  // clear out old errors
  $$('.val-err').invoke('hide');

  // remove from the fields
  $$('.field').each(function(e){
    if (e.hasClassName('error'))
      e.removeClassName('error')
  });
}


function form_presubmit_ok(frm) {
  var errors = $H();
  var custom_errors = new Array();

  // clear out old errors
  clear_errors();
  
  // check the form is ok to be sumbitted according to the form sepecifc validation
  if (window[frm.name+'_onSubmit']) {
    // errors will be populated with any errors
    window[frm.name+'_onSubmit'](frm, errors, custom_errors);
  }

  // check the required fields (unless they don't want us to)
  if (!frm.hasClassName('form-no-required')) {
    check_required(frm, errors);
  }

  // did we get past both stages of validation?
	if (errors.size() > 0 || custom_errors.length) {
	  if (window[frm.name+'_onValidationFailed'])
	    window[frm.name+'_onValidationFailed'](frm, errors, custom_errors);
    else
		  display_errors(errors, custom_errors);
			if($('field_validation')){location.href='#field_validation'}
	  return false;
	}

  // everything must be ok
  return true;
}


function display_errors(errors, custom_errors) {
  var had_error = false;
  
  errors.each(function(error){
    $$('.val-err').each(function(err){
      if (err.getMetaData().err == error[0]) {
        err.show();
        if (err.up('.validation'))
          err.up('.validation').show();
        had_error = true;
      }
    });
  });
  
  // scroll up to the error information
  if (had_error) {
    // find the fix visible one on the page
    var val = $$('.validation');
    if (val[0])
      val[0].scrollTo();
  }
}


/*
  validation helpers
*/

// attached to all forms by default
function check_required(frm, response) {
  frm = $(frm);
  
	// process the radio buttons first (if required one of them of each name needs to be checked)
	var radios = new Hash();  
	$$('#'+frm.name+' .required *').each( function(r) {
	  if (r.value != null && r.type && r.type == 'radio') {
      var last = radios.get(r.name);
      if (!last)
        radios.set(r.name, false);
      if (r.checked)
        radios.set(r.name, true);
	  }
	});
	
	// are all required fields complete?
	$$('#'+frm.name+' .required *').each( function(r) 
	{	   
	  if (r.value != null && r.type) 
	  {
	    if (r.type == 'radio' && !radios.get(r.name)) 
	    {
	      // already know this radio button has failed
	      validation_failed(response, r.name, 'required');
  		  error_field(r);
      // stuid fck
	    } 
	    else if (r.id.indexOf('__Config') == -1) 
	    {
	      if (Element.hasClassName(r, 'fck-field'))
	      {
	        if (FCKeditorAPI.GetInstance(r.id).GetData() == '') {
	          validation_failed(response, r.name, 'required');
	          error_field(r);
	        } else
	          unerror_field(r);
	      }
    		else if ('' == r.value.strip()) {
    		  validation_failed(response, r.name, 'required');
    		  error_field(r);
    		} else {
    		  unerror_field(r);
    		}
	    }
	  }
	});

	return response;
}

function validation_failed(errors, full_field_name, error_type) {
  errors.set(full_field_name+'.'+error_type, 1);
}

// useful for registration forms
function passwords_match(frm) {
  frm = $(frm);
  // check that the password fields are identical in the given form
  passwords = frm.getInputs("password");
  // passwords must match
  if (passwords[0].value != passwords[1].value) {
    display_notification('The passwords you entered do not match.');
    // highlight the fields
    passwords.each( function (element) {
      error_field(element);
    });
    return false;
  }
  return true;
}

// standard error highlighting code - just override these if you want
function error_field(fld) {
  fld = $(fld);
  if (fld.up && fld.up('.field'))
    fld.up('.field').addClassName('error');
}
function unerror_field(fld) {
  fld = $(fld);
  if (fld.up && fld.up('.field'))
    fld.up('.field').removeClassName('error');
}
