var ajaxRequest = new Class({

  Implements: [Options],

  options: {
    formSelector: 'form.ajaxForm',
    serviceURL: './',
    showLoader: true,
    async: true,
    formAutoFocus: true,
    loaderCss: 'ajaxLoader',
    confirmTextSelector: '.confirmSubmit',
    successTextSelector: '.submitSuccess',
    errorTextSelector: '.submitError',
    onBeforeSubmit: 'onBeforeSubmit',
    onNotConfirmSubmit: 'onNotConfirmSubmit',
    onAfterSubmit: 'onAfterSubmit',
    onSuccess: 'onSuccess',
    onFailure: 'onFailure',
    unloadPromptOn: true,
    msgUnloadFormChanged: localeMsgUnloadFormChanged,
    msgUnloadFormsChanged: localeMsgUnloadFormsChanged
  },
  formObjs: null,

  initialize: function(formObjs, options){
    this.setOptions(options);
    if ($defined(formObjs)) {
      this.formObjs = formObjs;
    } else {
      this.formObjs = $$(this.options.formSelector);
    }
    this.initForms();
    this.initUnload();
    if (this.options.formAutoFocus) {
      this.setFormFocus();
    }
  },

  initUnload: function(){
    window.onbeforeunload = function(e) {
      if (this.options.unloadPromptOn) {
        var exitPrompt = this.getExitPrompt();
        if (exitPrompt) {
          if (typeof e == 'undefined') {
            e = window.event;
          }
          if (e) {
            e.returnValue = exitPrompt;
          }
          return exitPrompt;
        }
      }
    }.bind(this);
  },

  getExitPrompt: function(){
    var i = 0;
    this.formObjs.each(function(item, index){
      if (this.getObjModified(item)) {
        i++;
      }
    }, this);
    if (i < 1) {
      return '';
    } else if (i == 1) {
      return this.options.msgUnloadFormChanged;
    } else if (i > 1) {
      return this.options.msgUnloadFormsChanged;
    }
  },

  initForms: function(){
    this.formObjs.each(function(item, index){
      if (this.getObjModified(item) == -1) {
        this.setObjModified(item, 0);

        if (Browser.Engine.trident) {
          $(item.get('id')).getElements('input, select, textarea').addEvents({
            'change': function(e){
              this.setObjModified(item, 1);
            }.bind(this),
            'reset': function(e){
              this.setObjModified(item, 0);
            }.bind(this)
          });
        } else {
          item.addEvents({
            'change': function(e){
              this.setObjModified(item, 1);
            }.bind(this),
            'reset': function(e){
              this.setObjModified(item, 0);
            }.bind(this)
          });
        }
        item.addEvents({
          'submit': function(e){
            e.stop();
            item.set('disabled', true);
            var onBeforeSubmit = item.retrieve(this.options.onBeforeSubmit, null);
            if ($defined(onBeforeSubmit)) {
              if (!onBeforeSubmit(item)) {
                item.set('disabled', false);
                return;
              }
            }
            var text = this.getSelectorObj(item, this.options.confirmTextSelector);
            if (text && text.get('text')) {
              item.store('confirmed', confirm(text.get('text')));
            } else {
              item.store('confirmed', true);
            }
            if (item.retrieve('confirmed', false)) {
              var formId = item.get('id');
              item.set('send', {
                url: this.options.serviceURL,
                async: this.options.async,
                onRequest: function(){
//console.log('Request Start');
                  $(formId).set('disabled', true);
                  this.showLoader($(formId));
                  return this;
                }.bind(this),
                onFailure: function(xhr){
//console.log('Request Failure');
                  $(formId).set('disabled', false);
                  this.hideLoader($(formId));
                  this.requestError(xhr, $(formId));
                  var fn = $(formId).retrieve(this.options.onFailure, null);
                  if ($defined(fn)) { fn($(formId)); }
                  return this;
                }.bind(this),
                onSuccess: function(responseText, responseXML){
//console.log('Request Success');
                  this.setObjModified($(formId), 0);
                  $(formId).set('disabled', false);
                  this.hideLoader($(formId));
                  this.processResponse(responseXML, $(formId));
                  var fn = $(formId).retrieve(this.options.onSuccess, null);
                  if ($defined(fn)) { fn($(formId)); }
                  this.requestSuccess($(formId));
                  return this;
                }.bind(this)
              }).send();
              var onAfterSubmit = item.retrieve(this.options.onAfterSubmit, null);
              if ($defined(onAfterSubmit)) { onAfterSubmit(item); }
            } else {
              item.set('disabled', false);
              var onNotConfirmSubmit = item.retrieve(this.options.onNotConfirmSubmit, null);
              if ($defined(onNotConfirmSubmit)) { onNotConfirmSubmit(item); }
            }
          }.bind(this)
        });
      }
    }, this);
  },

  setObjModified: function(obj, value){
    obj.store('isModified', value);
  },

  getObjModified: function(obj){
    return obj.retrieve('isModified', -1);
  },

  getSelectorObj: function(formObj, selector){
    var obj = formObj.getElements(selector);
    if (obj.length > 0) {
      return obj[0];
    }
    return null;
  },

  getSubmitInput: function(formObj){
    var submit = formObj.getElements('input[type=submit]');
    if (submit.length > 0) {
      return submit[0];
    }
    return null;
  },

  showLoader: function(formObj){
//console.log('Show Loader');
    if (this.options.showLoader) {
      var loader = $$('.'+formObj.get('id')+'.'+this.options.loaderCss);
      if (loader) {
        loader.setStyle('display', 'block');
      }
/*
      var objSubmit = this.getSubmitInput(formObj);
      if (objSubmit) {
        var div = new Element('div', {'class': this.options.loaderCss});
        div.inject(objSubmit, this.options.loaderPos);
      }
*/
    }
  },

  hideLoader: function(formObj){
    var loader = $$('.'+formObj.get('id')+'.'+this.options.loaderCss);
    if (loader) {
      loader.setStyle('display', 'none');
    }
  },

  requestSuccess: function(formObj){
    var textObj = this.getSelectorObj(formObj, this.options.successTextSelector);
    if (textObj && textObj.get('text')) {
      alert(textObj.get('text'));
    }
    var fn = formObj.retrieve('requestSuccess', null);
    if (fn){
      fn();
    }
  },

  requestError: function(xhr, formObj){
    var textObj = this.getSelectorObj(formObj, this.options.errorTextSelector);
    if (textObj && textObj.get('text')) {
      alert(textObj.get('text'));
    }
    var fn = formObj.retrieve('requestError', null);
    if (fn){
      fn(xhr);
    }
  },

  processResponse: function(responseXML, formObj){
//console.log('Process Response Start');
//    var resultNode = responseXML.getElementsByTagName('result');
    var resultNode = $try(function(){
      return responseXML.getElementsByTagName('result');
    }, function(){
      return [];
    });

    if(resultNode.length > 0 && resultNode[0].childNodes.length > 0) {
      resultNode = resultNode[0].childNodes;
      for(i = 0; i < resultNode.length; i++) {
        var dstObj = (resultNode[i].attributes && resultNode[i].attributes.getNamedItem('id')) ? $(resultNode[i].attributes.getNamedItem('id').nodeValue) : null;
        var firstChild = (resultNode[i].childNodes.length > 0) ? resultNode[i].firstChild.nodeValue : '';

        switch(resultNode[i].nodeName){
          case 'message': // message node
            if (firstChild) {
              alert(firstChild);
            }
            break;
          case 'confirm': // prompt node
            if (firstChild) {
              var actionOk = resultNode[i].attributes.getNamedItem('ok').nodeValue;
              var actionCancel = resultNode[i].attributes.getNamedItem('cancel').nodeValue;
              var action = (confirm(firstChild)) ? actionOk : actionCancel;
              dstObj.value = action;
              formObj.send(this.options.serviceURL);
            }
            break;
          case 'clearField': // clear field node
            dstObj.value = '';
            break;
          case 'setField': // set field value node
            if (dstObj) {
              dstObj.value = firstChild;
            }
            break;
          case 'checkField': // set field value node
            if (dstObj) {
              dstObj.checked = (firstChild == '1') ? true : false;
            }
            break;
          case 'setCombo': // set combo field value node
            if (dstObj) {
              dstObj.selectedIndex = firstChild;
            }
            break;
          case 'focusField': // make focus on field node
            dstObj.focus();
            dstObj.highlight(resultNode[i].attributes.getNamedItem('color').nodeValue);
            dstObj.select();
            break;
          case 'highlightField': // highlight a field node
            dstObj.highlight(resultNode[i].attributes.getNamedItem('color').nodeValue);
            break;
          case 'markObject': // mark an object by adding a css to the object
            dstObj.addClass(resultNode[i].attributes.getNamedItem('css').nodeValue);
            break;
          case 'unmarkObject': // unmark an object by deleting a css form the object
            dstObj.removeClass(resultNode[i].attributes.getNamedItem('css').nodeValue);
            break;
          case 'setHtml': // set Html content node
            dstObj.innerHTML = firstChild;
            break;
          case 'resetForm': // reset current form data
            formObj.reset();
            break;
          case 'resetOtherForm': // reset other form data
            dstObj.reset();
            break;
          case 'removeObject': // remove node
            if (dstObj) {
              dstObj.destroy();
            }
            break;
          case 'hideObject': // hide node
            dstObj.slide('hide');
            break;
          case 'showObject': // show node
            dstObj.slide('show');
            break;
          case 'slideInObject': // slide in node
            dstObj.slide('in');
            break;
          case 'slideOutObject': // slide out node
            dstObj.slide('out');
            break;
          case 'eval': // eval the js code
            try{
              eval(firstChild);
            }catch(e){
            }
            break;
          case 'runObjFn': // eval the js code
            try{
              var fn = dstObj.retrieve(resultNode[i].attributes.getNamedItem('name').nodeValue, $empty);
              var fnParam = firstChild;
              fn(fnParam);
            }catch(e){
            }
            break;
          case 'redirect': // redirect to URL
            window.location = firstChild;
            break;
          case 'sbMessage': // shadowbox message
            var msgTitle = resultNode[i].getElementsByTagName("title")[0].firstChild.nodeValue;
            var msgHtml = resultNode[i].getElementsByTagName("message")[0].firstChild.nodeValue;
            var msgWidth = resultNode[i].attributes.getNamedItem('width').nodeValue;
            var msgHeight = resultNode[i].attributes.getNamedItem('height').nodeValue;
            Shadowbox.open({
                content:        '<div id="sb-message-outter"><div id="sb-message-inner">'+msgHtml+'</div></div>',
                player:         'html',
                title:          msgTitle,
                width:          msgWidth,
                height:         msgHeight
            });
            break;
        } // switch
      } // for
    }
//console.log('Process Response End');
  },

  setFormFocus: function(){
    var objFields = $$('input:enabled:not([type="hidden"])');
    if (objFields.length > 0) {
      var exit = false;
      objFields.each(function(item){
        if (exit) return;
        try {
          item.focus();
          exit = true;
        } catch(err) {
        }
      });
    }
  }

});
window.addEvent('domready', function(){
  var formAjaxRequest = new ajaxRequest();
});
