var FabulousForm = $.klass({
  initialize: function(form_id, url, complete_func) {
    this.form_id = form_id;
    this.url = url;
    this.form = $('#'+form_id);
    this.parameters = this.form.serialize(true);
    this.name = null;
    this.submit_button = this.form.find('input[type=submit]');
    this.submit_button.init_value = this.submit_button.init_value != null ? this.submit_button.init_value : this.submit_button.val();
    this.complete_func = complete_func;
    this.active_class_name = 'fabulous_has_errors';

    this.errors_global_container = $('#'+this.form_id+' .fabulous_global_errors').first();
    this.errors_field_container = $('#'+this.form_id+' .fabulous_error_box').first();
  },

  clearErrors: function() 
  {
    this.templateCleaner();
    this.submit_button.val(this.submit_button.init_value);
    return this;
  },

  addGlobalError: function(err)
  {
    this.errors_global_container.append('<div class="fabulous_field_error_msg"> '+err+' </div>');
    return this;
  },

  addGlobalErrors: function(errors)
  {
    var self = this;
    errors.each(function(err){
      self.addGlobalError(err);
    });
    return this;
  },

  setName: function(name) 
  {
    this.name = name;
  },

  handleResponse: function(json)
  {
    if (!json) {
      this.throwError('json incorrect');
    }

    var is_valid = json['params'].is_valid;

    this.setName(json['params'].name);
    var params = json['params'];
    var errors = json['errors'];
    var global_errors = json['global_errors'];
    var focus_field = json['focus_field'];

    if (is_valid) {
      this.handleSuccess(params);
    } else {
      this.handleError(params, errors, global_errors, focus_field);
    }
  },

  handleSuccess: function(params)
  {
	this.submit_button.removeAttr("disabled");
    this.form.field_disabled.each(function() {
       //fix for chrome/safari and object HTMLOptionElement
       if (typeof $(this).disable === 'function') {
         $(this).disable();
       }
    })
    eval(this.complete_func);
  },

  handleError: function(params, errors, global_errors, focus_field) 
  {
    this.templateCleaner();

    form_name = this.name;

    node = $('#'+this.form_id+' .fabulous_error_box');
    if (node.length > 0 && errors.length > 0) {
      node.first().addClass(this.active_class_name);
      if (global_errors.length == 0) {
        node.first().addClass('first');
      }
    }

    var self = this;
    errors.each(function(err){
      var field = err.field_id;

      if (node.length > 0) {
        node.first().append('<div class="fabulous_field_error_msg"> ' + err.error + ' </div>');
      }

      if($('#'+self.form_id+' #'+field)) {
        $('#'+self.form_id+' #'+field).addClass('fabulous_field_error');
        if (node.length == 0) {
          $('<div class="fabulous_field_error_msg"> '+err.error+' </div>').insertAfter($('#'+field));
        }
      }
    });

    node = $('#'+this.form_id+' .fabulous_global_errors');
    if (node.length > 0 && global_errors.length > 0) {
      node.first().addClass(this.active_class_name);
      node.first().addClass('first');
    }

    var self = this;
    global_errors.each(function(err){
      // insert global message
      if (node.length > 0) {
        node.first().append('<div class="fabulous_global_error_msg"> '+err.error+' </div>');
      }

      // highlight fields
      err.fields.each(function(err_field){
        var field = err_field.field_id;
        if ($('#'+self.form_id+' #'+field)) {
          $('#'+self.form_id+' #'+field).addClass('fabulous_global_error');
        }
      });
    });

    if (this.submit_button.attr('message_error')) {
      this.submit_button.val(this.submit_button.attr('message_error'));
    } else {
      this.submit_button.val('errors...!');
    }

    var self = this;
    this.submit_button.effect("pulsate", {times:4}, 200, function(){
      self.submit_button.val(self.submit_button.init_value);
      self.submit_button.removeAttr("disabled");
    });

    //re enable le form
    this.form.field_disabled.each(function(){
      //fix for chrome/safari and object HTMLOptionElement
      if (typeof $(this).disable === 'function') {
        $(this).disable();
      }
    });

    if (focus_field) {
      var first_field_to_focus = params['name']+'_'+focus_field;
      if ($('#'+this.form_id+' #'+first_field_to_focus)) {
        $('#'+this.form_id+' #'+first_field_to_focus).focus();
      }
    }
    //this.form.scrollTo(); // jQuery doesnt have such a function, although we could use a plugin
  },

  throwError: function(msg)
  {
    alert(msg);
  },

  getFieldName: function(field)
  {
    alert(field);
    return this.name + '_' + field;
  },

  templateCleaner: function()
  {
    $('.fabulous_field_error').each(function(){
      $(this).removeClass('fabulous_field_error');
    });

    $('div.fabulous_field_error_msg').remove();

    $('#'+self.form_id+' .fabulous_error_box').first().removeClass(this.active_class_name);
    $('#'+self.form_id+' .fabulous_error_box').first().removeClass('first');

    $('.fabulous_global_error').each(function(){
      $(this).removeClass('fabulous_global_error');
    });

    $('div.fabulous_global_error_msg').remove();

    $('#'+self.form_id+' .fabulous_global_errors').first().removeClass(this.active_class_name);
    $('#'+self.form_id+' .fabulous_global_errors').first().removeClass('first');
  }
});

function fabulous_submit() 
{
  alert('error!');
}

function fabulous_process(form_id, url, complete_func, after_update_func) 
{
  var fabForm = new FabulousForm(form_id, url, complete_func);
  fabForm.form.field_disabled = fabForm.form.find(':disabled');

  $('#'+form_id+' input[type=\'submit\']').attr("disabled", "disabled");

  if (fabForm.submit_button.attr('message_loading')) {
    fabForm.submit_button.val(fabForm.submit_button.attr('message_loading'));
  } else {
    fabForm.submit_button.val('loading...');
  }

  $.ajax({
    type: 'POST',
    url: fabForm.url,
    data: (fabForm.parameters),
    processData: false,
    success: function(msg, status, request){
      fabForm.handleResponse($.parseJSON(request.getResponseHeader("X-Json")));
      if (after_update_func) {
        eval(after_update_func);
      }
    },
    beforeSend: function(xhr){
     xhr.setRequestHeader("fabulous", "true");
    },
    error: function(){
      alert('Ajax error');
    }
  });
}
