(function() {
  
  var Event = YAHOO.util.Event, Dom = YAHOO.util.Dom, Lang = YAHOO.lang;
  
  inputEx.yaTrainStationField = function(options) {
    inputEx.yaTrainStationField.superclass.constructor.call(this, options);
  };
  
  Lang.extend(inputEx.yaTrainStationField, inputEx.ExtAutoComplete, { 
  
    setOptions: function(options) {
      inputEx.yaTrainStationField.superclass.setOptions.call(this, options);
      
      this.options.className = 'inputEx-Field inputEx-AutoComplete inputEx-PickerField inputEx-yaStringLookup';
      
      this.options.dialogId = options.dialogId || Dom.generateId();
      this.options.dialogHeader = options.dialogHeader || '';
      this.options.contentUrl = options.contentUrl || window.location;
      this.options.selectorChars = options.selectorChars || 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      this.options.startChar = options.startChar || this.options.selectorChars.charAt(0);
      
      var that = this;
      
      this.ajaxCallback = {
          
        success: function(o) {
          that.setContent(o.responseText);
          that.hideMask();
          that.dataLoaded = true;
        },
        
        failure: function(o) {
          that.hideMask();
          that.oOverlay.hide();
          that.dataLoaded = false;
        },
        
        timeout: 60000
      };
      
      this.contentLoaded = false;
      
      this.selectedEl = null;
    },
  
    renderComponent: function() {
      inputEx.yaTrainStationField.superclass.renderComponent.call(this);
      
      this.oOverlay = new YAHOO.widget.Overlay(Dom.generateId(), { visible: false });
      this.oOverlay.setBody(" ");
      this.oOverlay.body.id = Dom.generateId();

      // Create button
      this.button = new YAHOO.widget.Button({ type:"menu", menu:this.oOverlay, label:"&nbsp;&nbsp;&nbsp;&nbsp;"});       
      this.button.appendTo(this.wrapEl);

      this.oOverlay.showEvent.subscribe(this.onOverlayShow, this, true);

      // Render the overlay
      this.oOverlay.render(this.wrapEl);
      // HACK: Set position absolute to the overlay
      Dom.setStyle(this.oOverlay.body.parentNode, "position", "absolute");
      Dom.setStyle(this.oOverlay.body.parentNode, "z-Index", "1000");
      
      this.selectorEl = inputEx.cn('div', { className: 'inputEx-yaStringLookup-Selector' });
      this.oOverlay.appendToBody(this.selectorEl);

      for (var i = 0; i < this.options.selectorChars.length; i++) {
        var char = this.options.selectorChars.charAt(i);
        var sEl = inputEx.cn('a', { href: '#' }, null, char);
        this.selectorEl.appendChild(sEl);
        
        if (char == this.options.startChar) {
          Dom.addClass(sEl, 'selected');
          this.selectedEl = sEl;
        }
      }
      
      this.selectorEl.appendChild(inputEx.cn('div', { className: 'inputEx-clear-div' }));
      
      YAHOO.util.Event.delegate(this.selectorEl, "click", this.onSelectorClick, 'a', this, true);

      this.contentEl = inputEx.cn('div', { className: 'inputEx-yaStringLookup-Content' });
      this.oOverlay.appendToBody(this.contentEl);
      this.oOverlay.appendToBody(inputEx.cn('div', { className: 'inputEx-clear-div' }));

      YAHOO.util.Event.delegate(this.contentEl, "click", this.onContentClick, 'a', this, true);
    },

    /**
     * Create a Mask over the form
     */
    renderMask: function() {
      if (this.maskRendered) return;

      // position as "relative" to position formMask inside as "absolute"
      Dom.setStyle(this.oOverlay.body, "position", "relative");

      // set zoom = 1 to fix hasLayout issue with IE6/7
      if (YAHOO.env.ua.ie) { Dom.setStyle(this.oOverlay.body, "zoom", 1); }

      // Render mask over the divEl
      this.overlayMask = inputEx.cn('div', {className: 'inputEx-Form-Mask'},
        {
           display: 'none',
           // Use offsetWidth instead of Dom.getStyle(this.divEl,"width") because
           // would return "auto" with IE instead of size in px
           width: this.oOverlay.body.offsetWidth+"px",
           height: this.oOverlay.body.offsetHeight+"px"
        },
        "<div class='inputEx-Form-Mask-bg'/><center><div class='inputEx-Form-Mask-spinner'></div><span>"+inputEx.messages.ajaxWait+"</span></div>"
      );
      
      this.oOverlay.appendToBody(this.overlayMask);
      this.maskRendered = true;
    },

    /**
     * Show the form mask
     */
    showMask: function() {
       this.renderMask();

       // Hide selects in IE 6
       this.toggleSelectsInIE(false);

       this.overlayMask.style.display = '';
    },

    /**
     * Hide the form mask
     */
    hideMask: function() {
       // Show selects back in IE 6
       this.toggleSelectsInIE(true);

       this.overlayMask.style.display = 'none';
    },
    
    /*
     * Method to hide selects in IE 6 when masking the form (else they would appear over the mask)
     */
    toggleSelectsInIE: function(show) {
      // IE 6 only
      if (!! YAHOO.env.ua.ie && YAHOO.env.ua.ie < 7) {
        var method = !!show ? Dom.removeClass : Dom.addClass;
        var that = this;
        Dom.getElementsBy(
          function() {return true;},
           "select",
           this.divEl,
           function(el) {method.call(that,el,"inputEx-hidden");}
        );
      }
    },
     
    setSelector: function(html) {
      this.selectorEl.innerHTML = html;
    },
    
    setContent: function(html) {
      this.contentEl.innerHTML = html;
    },
    
    getContentUrl: function(char) {
      return inputEx.strtr(this.options.contentUrl, { '%query%': char });
    },
    
    onSelectorClick: function(e, el) {
      Event.preventDefault(e);
      
      if (this.selectedEl) {
        Dom.removeClass(this.selectedEl, 'selected');
      }
      
      Dom.addClass(el, 'selected');
      this.selectedEl = el;
      
      this.showMask();
      YAHOO.util.Connect.asyncRequest('GET', this.getContentUrl(el.innerHTML), this.ajaxCallback);
    },
    
    onContentClick: function(e, el) {
      Event.preventDefault(e);
      this.setValue(el.innerHTML, false);
      this.oOverlay.hide();
    },
    
    onOverlayShow: function(e, args) {
      if (! this.dataLoaded) {
        this.showMask();
        YAHOO.util.Connect.asyncRequest('GET', this.getContentUrl(this.options.startChar), this.ajaxCallback);
      }
    }
    
  });
  
  inputEx.registerType("yaTrainStation", inputEx.yaTrainStationField);
  
})();



YAHOO.namespace("trainSearchForm");

YAHOO.trainSearchForm = function() {
  var event = YAHOO.util.Event, dom = YAHOO.util.Dom, lang = YAHOO.lang;

  return {
    init: function(options, formSchema, formValues) {
      this.options = {};
      this.form = null;
      this.formSchema = formSchema;
      this.formValues = formValues;
      
      if (! lang.isObject(options.messages)) options.messages = {};
      
      this.options.messages = {
        searching: options.messages.searching || 'Searching',
        loading: options.messages.loading || 'Loading',
        identicalStations: options.messages.identicalStations || 'Departure and Arrival stations cannot be identical.',
        trainNotFound: options.messages.trainNotFound || 'No trains were found. Please try to change search criteria.',
        connFailed: options.messages.connFailed || 'Connection failed. Please try again.',
        invalidResp: options.messages.invalidResp || 'Invalid response received from server. Please try again later.'
      };
    
      this.formSchema.ajax.callback = {
        success: this.successResponse,
        failure: this.failureResponse,
        timeout: 60000,
        scope: this
      };
      
      this.formSchema.buttons[0].onClick = { fn: this.submitForm, scope: this }
      
      this.progressPanel = null;

      event.onAvailable(this.formSchema.parentEl, this.formContReady, this, true);
    },
    
    setFormValues: function(formValues) {
      var len = formValues.length;
      for (i = 0; i < len; i++) {
        var field = this.getField(formValues[i].name);
        if (field != null) field.setValue(formValues[i].value);
      }
    },
    
    setFormErrors: function(formErrors) {
      var len = formErrors.length;
      for (i = 0; i < len; i++) {
        var field = this.getField(formErrors[i].name);
        if (field != null) {
          field.displayMessage(formErrors[i].error);
          dom.replaceClass(field.divEl, "inputEx-valid", "inputEx-invalid" );
        }
      }
    },
    
    formContReady: function() {
      this.form = new inputEx.Form(this.formSchema);
      
      if (YAHOO.lang.isArray(this.formValues)) {
        this.setFormValues(this.formValues);
      }
      
      this.getField('trip_type').updatedEvt.subscribe(this.changeRoundtrip, this, true);
    },
    
    changeRoundtrip: function(e, args) {
      var value= args[0];
      
      var field = this.getField('return_date');

      if (value) {
        dom.addClass(field.divEl, 'inputEx-required');
        field.options.required = true;
      } else {
        dom.removeClass(field.divEl, 'inputEx-required');
        field.options.required = false;
        field.setClassFromState();
      }
    },
    
    getField: function(name) {
      var fieldName = this.formSchema.fieldFormat.replace('%s', name, 'g');
      return this.form.getFieldByName(fieldName);
    },
    
    isRoundTrip: function() {
      return this.getField('trip_type').getValue();
    },
    
    submitForm: function(e) {
      if (this.validateForm()) {
        this.showProgressPanel(this.options.messages.searching);
        this.form.submitEvent.fire();
      }
    },
    
    validateForm: function() {
      var result = this.form.validate();
      if (! result) {
        return result;
      };

      result = this.validateFromTo();
      return result;
    },
    
    validateFromTo: function() {
      var result = true;
      var fromField = this.getField('from');
      var toField = this.getField('to');
      if (fromField.getValue() != '' && fromField.getValue().toLowerCase() == toField.getValue().toLowerCase()) {
        result = false;
        toField.displayMessage(this.options.messages.identicalStations);
      }
      return result;
    },
    
    showProgressPanel: function(message) {
      if (this.progressPanel == null) {
        this.progressPanel = new YAHOO.widget.Panel("progressPanel", { 
          width: "120px",
          constraintoviewport: false,
          fixedcenter: false,
          close: false,
          draggable: false,
          modal: true,
          visible: false,
          context: ['content', 'tl', 'tl', ["beforeShow", "windowResize"], [330, 150]]
        });
      }
      
      this.progressPanel.setBody('<div class="progressSpinner"><span class="message">' + message + '</span><img src="/images/spinner.gif" alt=""/></div>');
      this.progressPanel.render(document.body);
      this.progressPanel.show();
      YAHOO.util.Dom.setStyle('progressPanel_mask', 'z-index', 1000);
      YAHOO.util.Dom.setStyle('progressPanel_c', 'z-index', 1001);
    },
    
    hideProgressPanel: function() {
      if (this.progressPanel != null) {
        this.progressPanel.hide();
      }
    },
    
    successResponse: function(o) {
      this.hideProgressPanel();
      
      if (! YAHOO.lang.JSON.isSafe(o.responseText)) {
        alert(this.options.messages.invalidResp);
        return;
      }
      
      var response = YAHOO.lang.JSON.parse(o.responseText);

      if (response.form_errors) {
        this.setFormErrors(response.form_errors);
        return;
      }
        
      if (response.result[0].found > 0 && (! this.isRoundTrip() || response.result[1].found > 0)) {
        this.showProgressPanel(this.options.messages.loading);
        window.location = response.next;
        return;
      }
      
      alert(this.options.messages.trainNotFound);
    },
    
    failureResponse: function(o) {
      this.hideProgressPanel();
      alert(this.options.messages.connFailed);
    }
  };
}();
