var FabulousForm = $.klass({
  initialize: function(form_id, url, complete_func, options) {
    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.options = options || {}
    if (this.submit_button.init_value == null)
    {
      this.submit_button.init_value = new Array();
      for (var i = 0; i < this.submit_button.length; i++)
      {
        this.submit_button.init_value[i] = $(this.submit_button[i]).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();

    this.field_error_box_template = this.options.field_error_box_template ? this.options.field_error_box_template : '<div class="%FIELD_ERROR_BOX_CLASS%"> %ERROR% </div>';
    this.field_error_box_class = this.options.field_error_box_class ? this.options.field_error_box_class : 'fabulous_field_error_msg';
    this.field_error_box_template = this.field_error_box_template.replace('%FIELD_ERROR_BOX_CLASS%', this.field_error_box_class);
    
    this.global_error_box_template = this.options.global_error_box_template ? this.options.global_error_box_template : '<div class="%GLOBAL_ERROR_BOX_CLASS%"> %ERROR% </div>';
    this.global_error_box_class = this.options.global_error_box_class ? this.options.global_error_box_class : 'fabulous_global_error_msg';
    this.global_error_box_template = this.global_error_box_template.replace('%GLOBAL_ERROR_BOX_CLASS%', this.global_error_box_class);
  },

  clearErrors: function() 
  {
    this.templateCleaner();
    for (var i = 0; i < this.submit_button.length; i++)
    {
      $(this.submit_button[i]).val(this.submit_button.init_value[i]);
    }
    return this;
  },

  addGlobalError: function(err) {
    this.errors_global_container.append(this.field_error_box_template.replace('%ERROR%', err));
    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);
      try{
       $.colorbox.resize();
      }catch(Exception){}
    }
  },

  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);
  },
  
  showErrorAsAlert: function(params, errors, global_errors, focus_field) {
    var m = '';
    errors.each(function(err) {
      var field = err.field_id;
      m += err.error + "\n";
      if ($('#' + field)) {
        $('#' + field).addClass('fabulous_field_error');
      }

    })
    global_errors.each(function(err){
      m += err.error + "\n";

      // highlight fields
      err.fields.each(function(err_field){
        var field = err_field.field_id;
        if ($('#'+field)) {
          $('#'+field).addClass('fabulous_global_error');
        }
      });
    });
    alert(m);
  },
  showErrorAsDiv: function(params, errors, global_errors, focus_field) {
    this.templateCleaner();
    form_name = this.name;
    var self = this;

    node = $('#'+form_name+' .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');
      }
    }

    errors.each(function(err){
      var field = err.field_id;
      if (node.length > 0) {
        node.first().append(self.field_error_box_template.replace('%ERROR%', err.error));
      }
      
      if($('#'+field)) {
    	if(self.options.setValidateResult){
    	  if(typeof field === "undefined"){
    		 eval(self.options.setValidateResult+'("global",err.error);');
		  } else {
    		eval(self.options.setValidateResult+'(field,err.error);');
		  }
    	} else {
          $('#'+field).addClass('fabulous_field_error');
          if (node.length == 0) {
            $(self.field_error_box_template.replace('%ERROR%', err.error)).insertAfter($('#'+field));
          }
    	}
      }
    });

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

    global_errors.each(function(err){
      // insert global message
      if ( !self.options.setValidateResult && node.length > 0) {
        node.first().append(self.global_error_box_template.replace('%ERROR%', err.error));
      }
      if(err.fields.length == 0){
    	
	    eval(self.options.setValidateResult+'("global",err.error);');
      }
      // highlight fields
      err.fields.each(function(err_field){
        var field = err_field.field_id;
        if ($('#'+field)) {
    	  if(self.options.setValidateResult){
       	    eval(self.options.setValidateResult+'(field,err.error);');
       	  } else {
            $('#'+field).addClass('fabulous_global_error');
       	  }
        }
      });
    });
    $('#'+form_name+' .fabulous_error_box').show();
    
    if(!self.options.setValidateResult){
      $('#'+form_name+' .error-container').show();
    }
  },
  handleError: function(params, errors, global_errors, focus_field) 
  {
    form_name = this.name;
    var self = this;
    
    if (this.submit_button.attr('message_error')) {
      this.submit_button.val(this.submit_button.attr('message_error'));
    } else {
      this.submit_button.val('errors...!');
    }
    this.submit_button.effect("pulsate", {times:4}, 200, function(){
      for (var i = 0; i < self.submit_button.length; i++)
      {
        $(self.submit_button[i]).val(self.submit_button.init_value[i]);
      }
      self.submit_button.removeAttr("disabled");
    });
    if (this.options.alert_message == true) 
    {
      this.showErrorAsAlert(params, errors, global_errors, focus_field);
    }
    else
    {
      this.showErrorAsDiv(params, errors, global_errors, focus_field);
    }

    //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 ($('#'+first_field_to_focus)) {
        $('#'+first_field_to_focus).focus();
      }
    }
    
    if (this.options.no_scroll != 1){
	    if (this.options.alert_message != true && !this.isColorboxOpen() ) {
	      if(self.options.setValidateResult){
	    	if($('.incorrect').length>0){
	    	  setTimeout("window.scrollTo(0,($('.incorrect').first().offset().top)-20);",1)
	    	}
	      } else {
		    //I use timeout to hack focus for IE
		    setTimeout("window.scrollTo(0,$('#"+this.form_id+" .fabulous_has_errors').first().offset().top-30);",1)
	      }
	    }
  	}
  },

  isColorboxOpen: function()
  {
	if ($("#colorbox").css("display")=="block") {  
      return true;  
    }else{  
      return false;  
    }  
  },

  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.'+this.field_error_box_class).remove();
    
    $('#'+this.name+' .fabulous_error_box').hide();

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

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

    $('div.'+this.global_error_box_class).remove();

    $('#'+this.name+' .fabulous_global_errors').first().removeClass(this.active_class_name);
    $('#'+this.name+' .fabulous_global_errors').first().removeClass('first');
    
    $('.validate').each(function(){
    	$(this).removeClass('incorrect');
    	$(this).removeClass('short_incorrect');
    });
    $('.error-container').css('display','none');
  }
});

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

function fabulous_process(form_id, url, complete_func, after_update_func, options) 
{

  var fabForm = new FabulousForm(form_id, url, complete_func, options);
  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');
    }
  });

}
