DOM.addEventListener(window, 'load', function () {

  with (document) {
    var person   = getElementById('person'),
        callednr = getElementById('callednr'),
        phone    = getElementById('phone'),
        email    = getElementById('email'),
        date     = getElementById('date'),
        hour     = getElementById('hour'),
        minute   = getElementById('minute'),
        zone     = getElementById('zone'),
        numkeys  = [8,9,35,36,37,38,39,40,46,48,49,50,51,52,53,54,55,56,57,63272,63273,63275,63232,63233,63234,63235];
  }

  // events
  person.onkeypress = email.onkeypress = function (e) {
    var e = e||window.event, c = e.keyCode||e.charCode;
    return c !== 10 && c !== 13;
  }
  phone.onkeypress = function (e) {
    var e = e||window.event, c = e.keyCode||e.charCode;
    return c !== 10 && c !== 13 && numkeys.indexOf(c) !== -1;
  }
  date.onchange = function (e) {
    hour.disabled = minute.disabled = (date.selectedIndex == 0);
  }

  // init pickup/dropoff pane
  function init (p, e) {
    with (document) {
      var search    = getElementById(p+'search'),
          loader    = getElementById(p+'loader'),
          choice    = getElementById(p+'choice'),
          select    = getElementById(p+'select'),
          lid       = getElementById(p+'lid'),
          place     = getElementById(p+'location'),
          sid       = getElementById(p+'sid'),
          street    = getElementById(p+'street'),
          number    = getElementById(p+'number'),
          entrance  = getElementById(p+'entrance'),
          pickup    = (p == 'pickup_'),
          notFound  = getElementById('error-'+e),
          xhr, callback;
    }
    // hide choice pane
    function hide () {
      choice.style.display = 'none';
      select.selectedIndex = -1;
      lid.value = sid.value = place.value = '';
      DOM.removeChildren(select);
    }
    // pick fetched result from select
    function pick () {
      var address = select.options[select.selectedIndex].address;
      lid.value      = address.lid;
      place.value    = address.location;
      sid.value      = address.sid;
      street.value   = address.street;
      number.value   = address.number||'';
      entrance.value = address.entrance||'';
      street.updated();
      number.updated();
      entrance.updated();
    }
    // fetch addresses
    function fetch (f) {
      if (!street.value.length) return;
      if (zone.selectedIndex < 1) return;
      choice.style.display = 'none';
      notFound.style.display = 'none';
      loader.style.display = 'block';
      if (xhr) xhr.abort();
      xhr = new XMLHttpRequest();
      xhr.open('POST', '/json/address/', true);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 
      xhr.setRequestHeader('If-Modified-Since', 'Thu, 1 Jan 1970 00:00:00 GMT');
      xhr.onreadystatechange = function () {
        if (xhr.readyState !== 4) return;
        loader.style.display = 'none';
        select.selectedIndex = -1;
        DOM.removeChildren(select);
        if (xhr.status !== 200) return alert(xhr.statusText);
        JSON.parse(xhr.responseText).forEach(function (address) {
          var option = document.createElement('OPTION'),
              text = address.street;
          if (address.number) text += ' '+address.number+(address.entrance||'');
          text += ', '+address.location;
          option.appendChild(document.createTextNode(text));
          option.value = address.sid;
          option.address = address;
          select.appendChild(option);
        });
        switch (select.options.length) {
          case 0:
            notFound.style.display = 'block';
            street.focus();
            break;
          case 1:
            choice.style.display = 'block';
            select.selectedIndex = 0;
            pick();
            if (f !== false) select.focus();
            break;
          default:
            choice.style.display = 'block';
            select.selectedIndex = 0;
            for (var i = 0, option; option = select.options[i]; i++) {
              if (option.value === sid.value) {
                select.selectedIndex = i;
                break;
              }
            }
            pick();
            if (f !== false) select.focus();
            break;
        }
      }
      xhr.send(
        'called='    + callednr.value +
        '&calling='  + phone.value +
        '&street='   + encodeURIComponent(street.value) +
        '&number='   + number.value +
        '&entrance=' + entrance.value +
        '&zone='     + zone.options[zone.selectedIndex].value +
        '&pickup='   + pickup
      );
      return false;
    }

    // events
    DOM.addEventListener(street, 'change', hide);
    DOM.addEventListener(number, 'change', hide);
    DOM.addEventListener(zone,   'change', hide);
    DOM.addEventListener(select, 'change', pick);
    DOM.addEventListener(search, 'click',  fetch);
    street.onkeypress = entrance.onkeypress = function (e) {
      var e = e||window.event, c = e.keyCode||e.charCode;
      if (c === 10 || c === 13) return fetch();
    };
    number.onkeypress = function (e) {
      var e = e||window.event, c = e.keyCode||e.charCode;
      if (c === 10 || c === 13) return fetch();
      return numkeys.indexOf(c) !== -1;
    }

    // pre-load
    fetch(false);
  }
  init('pickup_', 500);
  init('dropoff_', 501);
});
