Forms = {}

Forms.FocusFirstField = Behavior.create({
  initialize: function() {
    this.focusFirstField.bind(this).delay(0.1);
  },
  focusFirstField: function() {
    this.element.down('input[type=text]').focus();
  }
});

Forms.FocusField = Behavior.create({
	initialize: function() {
		this.focusField.bind(this).delay(0.1);
	},
	focusField: function() {
		this.element.focus();
	}
});

Event.addBehavior({
  'form#new_user': Forms.FocusFirstField,
  'form#new_session': Forms.FocusFirstField,
  'form#reset_password': Forms.FocusFirstField
});

Event.addBehavior({
	'form input.focused' : Forms.FocusField
});

Forms.ButtonTo = {
  /**
   * ButtonTo Confirmation
   * ----
   * Generates the confirmation message from the text of the button, if the form does not contain a child element with a
   * class of 'confirmationMessage'.
   */
  Confirmation : Class.create(Confirmation, {
    getMessage : function($super, e) {
      var message = $super(e);
      if (message == null || message == '') {
        var sourceElement = e.element();
        action = sourceElement.value.replace(/^(.)/, function(match) { return match.toLowerCase(); });
        message = 'Are you sure you want to ' + action + '?';
      }

      return message;
    }
  })
}

Forms.Remote = Class.create(Remote.Base, {
  progressIndicator : ProgressIndicator.Spinner,
  evalJS : true,

  initialize : function($super, options) {
    if (options == null) options = {};
    if (options.evalJS) {
      this.evalJS = options.evalJS;
      options.evalJS = null;
    }

    onCompleteWrapper = function(original, response) {
      this.options.progressIndication.stop();
      this.options.sourceElement.form.enable();        

      // Evaluate scripts returned in the response if evalJS is true (default).
      // This is here to ensure that all pure-JS behavior is processed before processing
      // scripts in the response, in case the response scripts modify elements of the DOM
      // that the pure-JS behavior needs to operate on in a general way after the request.
      this.evaluateScripts(response);

      original(response);
 			
      // Re-attach Lowpro behaviors, in case the DOM changed
      Event.addBehavior.reload();
    };
    
    if(options.onComplete) {
      options.onComplete = options.onComplete.wrap(onCompleteWrapper);
    } else {
      options.onComplete = (function() {}).wrap(onCompleteWrapper);
    }
      
    $super(options);
  },
  
  evaluateScripts : function(response) {
    var contentType = response.getHeader('Content-type');
    if (this.evalJS == 'force'
        || (this.evalJS && contentType
        && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
      response.request.evalResponse.apply(response.request);
  },
    
  onclick : function(e) {
    // Note: 
    //   LowPro's default implementation of Remote.Form has the following functionality split
    //   between onclick and onsubmit. However, it all needs to happen in onclick, because:
    //     - IE does not submit the form if onclick is defined on the 'submit' button
    //     - calling form.submit() does not trigger the onsubmit event
    var sourceElement = e.element();
    this.options.sourceElement = sourceElement;
    this.options.progressIndication = this.progressIndicator.start(sourceElement);
    this.submitRequest(sourceElement);
    sourceElement.form.disable();

    e.stop();
    return false;      
  },
  submitRequest : function(submitButton) {
    var form = submitButton.form;
    var options = Object.extend({
      url : form.action,
      method : form.method || 'get',
      evalJS : false, // disabling js eval until after Form.Remote is done with its onComplete stuff
      parameters : form.serialize({ submit: submitButton.name })
    }, this.options);
    return this._makeRequest(options);
  }  
});

// TODO: create function to generate this code:
// CSS selector with conditionals: 'form.(remote|confirm) (input|button)[type=submit]'
var formSelectors = combineElements(
  combineElements(
    combineElements(
      ['form'], 
      ['.remote', '.confirm']
    ), 
    [' input', ' button']
  ), 
  ['[type=submit]']
).join(',');

Event.addBehavior((function() {
  behaviorSelectors = {};
  behaviorSelectors[formSelectors] = Behavior.create({
    onclick : function(e) {
      var sourceElement = e.element();
      var form = $(sourceElement.form), handler = null;

      if (form.match('.remote'))
        handler = new Forms.Remote();

      if (form.match('.button-to.confirm'))
        handler = new Forms.ButtonTo.Confirmation(sourceElement, handler.onclick.bind(handler, e));
      else if (form.match('.confirm'))
        handler = new Confirmation(sourceElement, handler.onclick.bind(handler, e));

      if (handler) return handler.onclick(e);
    }
  });
  return behaviorSelectors;
})());