var yaTrainSearch = function(cfg) {
  cfg = cfg == undefined ? new Array() : cfg;
  
  if (YAHOO.lang.isUndefined(cfg.method)) {
    cfg.method = 'POST';
  }
  if (YAHOO.lang.isUndefined(cfg.url)) {
    cfg.url = null;
  }
  if (YAHOO.lang.isUndefined(cfg.timeout)) {
    cfg.timeout = 600000;
  }
  if (YAHOO.lang.isUndefined(cfg.onSuccess)) {
    cfg.onSuccess = null;
  }
  if (YAHOO.lang.isUndefined(cfg.onFailure)) {
    cfg.onFailure = null;
  }
  if (YAHOO.lang.isUndefined(cfg.onInvResponse)) {
    cfg.onInvResponse = null;
  }
  
  this.cfg = cfg;
  
  this.cfg.err = { 
    conFailed:'Connection error. Please, try again later.',
    invResp:'Invalid response from server. Please, try again.'
  };

  this.init();
}

yaTrainSearch.prototype = {
  init:function() {
    this.searchCallback = {success:this.hSearchSuccess, failure:this.hSearchFailure, scope:this, timeout: this.cfg.timeout};
    this.conn = YAHOO.util.Connect;
    this.form = null;
    this.result = null;
  },
  
  setForm:function(form) {
    this.form = form;
    this.conn.setForm(form);
  },
  
  isRoundtrip:function() {
    return this.form['trip_type'].checked;
  },
  
  startSearch:function() {
    this.conn.asyncRequest('POST', this.cfg.url, this.searchCallback);
  },
  
  hSearchSuccess:function(o) {
    this.result = null;
    if (!YAHOO.lang.JSON.isSafe(o.responseText)) {
      if (this.cfg.onInvResponse != null) {
        this.cfg.onInvResponse(o);
      } else {
        alert(this.cfg.err.invResp);
      }
      return;
    }
    
    var response = YAHOO.lang.JSON.parse(o.responseText);
    
    if (isUndefined(response.searchResult) || isUndefined(response.searchResult['0']) || isUndefined(response.searchResult['0'].found) || 
        (this.isRoundtrip() && (isUndefined(response.searchResult['1']) || isUndefined(response.searchResult['1'].found)))) {
      if (this.cfg.onInvResponse != null) {
        this.cfg.onInvResponse(o);
      } else {
        alert(this.cfg.err.invResp);
      }
      return;
    }
    
    this.result = response.searchResult;
    
    if (this.cfg.onSuccess != null) {
      this.cfg.onSuccess(this.result);
    }
  },
  
  hSearchFailure:function(o) {
    if (this.cfg.onFailure != null) {
      this.cfg.onFailure(o);
    } else {
      alert(this.cfg.err.conFailed);
    }
  }
}

var yaTrainSearchForm = function(cfg) {
  cfg = cfg == undefined ? new Array() : cfg;
  
  if (YAHOO.lang.isUndefined(cfg.depDateErrCont)) {
    cfg.depDateErrCont = null;
  }
  
  if (YAHOO.lang.isUndefined(cfg.retDateErrCont)) {
    cfg.retDateErrCont = null;
  }
  
  if (YAHOO.lang.isUndefined(cfg.dateFormatRegexp)) {
    cfg.dateFormatRegexp = null;
  }
  
  this.cfg = cfg;
  
  this.cfg.err = { 
    conn:'Connection error. Please, try again later.',
    sameSt:'Departure and Arrival stations could not be the same.',
    misDepSt:'Please, select Departure station',
    misArrSt:'Please, select Arrival station',
    unkSt:'Unknown or unsupported station',
    misDepDate:'Please, enter departure date.',
    misRetDate:'Please, enter return date.',
    invDepDate:'Please, enter valid departure date.',
    invRetDate:'Please, enter valid return date.',
    minDepDate:'Departure date must be equal or after %min_date%.',
    minRetDate:'Return date must be the same as departure or later.'
  };
  
  YAHOO.widget.DateMath.clearTime(this.cfg.minDate);
  YAHOO.widget.DateMath.clearTime(this.cfg.maxDate);
  this.cfg.dateFields=this.cfg.dateInputFormat.toString().split(this.cfg.dateFormatDelim);
  
  this.init();
}

yaTrainSearchForm.prototype = {
  init:function() {
    this.form = this.cfg.form;
    this.stations = this.cfg.stations;
    this.dateFieldsOrder = {y:array_search('%year%', this.cfg.dateFields), m:array_search('%month%', this.cfg.dateFields), d:array_search('%day%', this.cfg.dateFields)};
    
    Event.addListener(this.form['departure_date'], "blur", this.depDateOnBlur, this, true);
    Event.addListener(this.form['return_date'], "blur", this.retDateOnBlur, this, true);
    Event.addListener(this.form['trip_type'], "click", this.tripTypeOnClick, this, true);
    Event.addListener(this.form['popular_departure_stations'], "change", this.popDepStOnChange, this, true);
    Event.addListener(this.form['popular_arrival_stations'], "change", this.popArrStOnChange, this, true);
    
    this.setRoundtrip(this.form['trip_type'].checked);
  },

  getStationByName:function(name) {
    name = name.trim();
    for (i = 0; i < this.stations.length; i++) {
      if (this.stations[i].t.toUpperCase() == name.toUpperCase()) {
        return this.stations[i];
      }
    }
    return false;
  },
  
  parseDate:function(dateString) {
    var a = dateString.split(this.cfg.dateFormatDelim);
    if (a.length != 3) {
      return false;
    }
    if (this.cfg.dateFormatRegexp != null && !dateString.match(this.cfg.dateFormatRegexp)) {
      return false;
    }
    date = new Date(a[this.dateFieldsOrder.y], a[this.dateFieldsOrder.m] - 1, a[this.dateFieldsOrder.d]);
    YAHOO.widget.DateMath.clearTime(date);
    return date;
  },
  
  isRoundtrip:function() {
    return this.form['trip_type'].checked;
  },

  renderFieldError:function(error) {
    return '<li>' + error + '</li>';
  },
  
  displayFormError:function(error, container) {
    if (container != null && !YAHOO.lang.isUndefined(container)) {
      if (YAHOO.lang.isString(container)) {
        container = Dom.get(container);
      }
      container.innerHTML = this.renderFieldError(error);
    } else {
      alert(error);
    }
  },
  
  clearFormError:function(container) {
    if (YAHOO.lang.isString(container)) {
      container = Dom.get(container);
    }
    
    var el = new YAHOO.util.Element(container);
    while (el.hasChildNodes()) {
      el.removeChild(el.get('firstChild'));
    }
    
    container.style.height = 0;
  },
  
  setRoundtrip:function(roundtrip) {
    if (!roundtrip){
      this.form['return_date'].value = '';
    } else {
      var value = '';
      var depDate = this.parseDate(this.form['departure_date'].value);
      if (depDate != false) {
        value = formatDateInputValue(this.cfg.dateInputFormat, YAHOO.widget.DateMath.add(depDate, YAHOO.widget.DateMath.DAY, 7));
      }
      this.form['return_date'].value = value;
    }
    
    this.form['return_date'].disabled = !roundtrip;
    this.form['trip_type'].checked = roundtrip;
    this.clearFormError(this.cfg.retDateErrCont);
    
    if (! YAHOO.lang.isUndefined(this.cfg.onTripTypeChange)) {
      this.cfg.onTripTypeChange(roundtrip);
    }
  },
  
  checkDepDate:function(depDate) {
    var result = true;
    var error = null;
    var date = depDate;

    if (YAHOO.lang.isString(depDate)) {
      date = this.parseDate(depDate);
    }

    if (date === null || YAHOO.lang.isUndefined(date)){
      result = false;
      error = this.cfg.err.misDepDate;
    } else if (date === false || !checkDate(date.getFullYear(), date.getMonth(), date.getDate())){
      result = false;
      error = this.cfg.err.invDepDate;
    } else if (date.getTime() < this.cfg.minDate.getTime()){
      result = false;
      error = strtr(this.cfg.err.minDepDate, {'%min_date%':formatDateInputValue(this.cfg.dateInputFormat, this.cfg.minDate)});
    }
    
    if (!result && error != null) {
      this.displayFormError(error, this.cfg.depDateErrCont);
    } else if (result) {
      this.clearFormError(this.cfg.depDateErrCont);  
    }

    return result;
  },
  
  checkRetDate:function(retDate, depDate) {
    if (!this.isRoundtrip()) {
      return true;
    }

    var result = true;
    var error = null;
    var date = retDate;

    if (YAHOO.lang.isString(retDate)) {
      date = this.parseDate(retDate);
    }
    
    if (date === null || YAHOO.lang.isUndefined(date)){
      result = false;
      error = this.cfg.err.misRetDate;
    } else if (date === false || !checkDate(date.getFullYear(), date.getMonth(), date.getDate())) {
      result = false;
      error = this.cfg.err.invRetDate;
    } else if (depDate !== false && depDate !== null && !YAHOO.lang.isUndefined(date) && (depDate.getTime() > date.getTime())) {
      result = false;
      error = this.cfg.err.minRetDate;
    }
    
    if (!result && error != null) {
      this.displayFormError(error, this.cfg.retDateErrCont);
    } else if (result) {
      this.clearFormError(this.cfg.retDateErrCont);  
    }

    return result;
  },
  
  checkStationName:function(name) {
    return (this.getStationByName(name) != false);
  },
  
  checkDepSt:function() {
    var value = this.form['departure_station_name'].value;
    if (value == '') {
      this.displayFormError(this.cfg.err.misDepSt, this.cfg.depStNameErrCont);
      return false;
    } else if (!this.checkStationName(value)) {
      this.displayFormError(this.cfg.err.unkSt, this.cfg.depStNameErrCont);
      return false;
    } else if (this.form['arrival_station_name'].value != '') {
      this.checkArrSt();
    }
      
    this.clearFormError(this.cfg.depStNameErrCont);
    return true;
  },
  
  checkArrSt:function() {
    var value = this.form['arrival_station_name'].value;
    if (value == '') {
      this.displayFormError(this.cfg.err.misArrSt, this.cfg.arrStNameErrCont);
      return false;
    } else if (!this.checkStationName(value)) {
      this.displayFormError(this.cfg.err.unkSt, this.cfg.arrStNameErrCont);
      return false;
    } else if (value.toUpperCase() == this.form['departure_station_name'].value.toUpperCase()) {
      this.displayFormError(this.cfg.err.sameSt, this.cfg.arrStNameErrCont);
      return false;
    }
    this.clearFormError(this.cfg.arrStNameErrCont);
    return true;
  },
  
  validate:function() {
    var depDate = this.form['departure_date'].value;
    var retDate = this.form['return_date'].value;
    var result = this.checkDepSt();
    var result = result && this.checkArrSt();
    var result = result && this.checkDepDate(depDate);
    var result = result && this.checkRetDate(retDate, this.parseDate(depDate));
    return result;
  },
  
  depDateOnBlur:function(e) {
    var depDate = this.form['departure_date'].value;
    var retDate = this.form['return_date'].value;
    if (this.checkDepDate(depDate)) {
      this.checkRetDate(retDate, this.parseDate(depDate));
    }
  },
  
  retDateOnBlur:function(e) {
    var retDate = this.form['return_date'].value;
    var depDate = this.form['departure_date'].value;
    if (this.checkRetDate(retDate, this.parseDate(depDate))) {
      this.checkDepDate(depDate);
    }
  },
  
  tripTypeOnClick:function(e) {
    this.setRoundtrip(this.form['trip_type'].checked);
  },

  popDepStOnChange:function(e) {
    if (this.form['popular_departure_stations'].selectedIndex != 0) {
      Event.preventDefault(e);
      this.form['departure_station_name'].value = this.form['popular_departure_stations'].value;
      this.checkDepSt();
    }
  },

  popArrStOnChange:function(e) {
    if (this.form['popular_arrival_stations'].selectedIndex != 0) {
      Event.preventDefault(e);
      this.form['arrival_station_name'].value = this.form['popular_arrival_stations'].value;
      this.checkArrSt();    
    }
  }
}
