function addEvent(obj, type, fn) {
  if (obj.addEventListener) {
    if (type == 'mousewheel') {
      type = 'DOMMouseScroll';
    };

    obj.addEventListener( type, fn, false );
  } else if (obj.attachEvent) {
    obj["e"+type+fn] = fn;
    obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
    obj.attachEvent( "on"+type, obj[type+fn] );
  }
}

function $(id) {
  return document.getElementById(id);
}

function createXMLHttpRequest() {
  var xmlhttp;

  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = new XMLHttpRequest();
    };
  };

  return {
    xmlhttp: xmlhttp,
    readyState: 0,
    responseXML: null,
    responseText: "",
    onsuccess: null,
    url: "",
    sent: "",
    async: 1,
    onsuccesscalled: false,

    onreadystatechange: function() {
    },

    open: function(method, url, mode) { 
      var obj = this;

      this.xmlhttp.onreadystatechange = function () {
        obj.readyState = obj.xmlhttp.readyState;

        if (obj.xmlhttp.readyState == 4) {
          obj.responseXML  = obj.xmlhttp.responseXML;
          obj.responseText = obj.xmlhttp.responseText;

          if (obj.onsuccess) { 
            obj.onsuccesscalled = true;
            obj.onsuccess(); 
          };
        };

        obj.onreadystatechange();
      };

      var ts = new Date;
      if (url.indexOf('?') == -1) {
        url = url + "?_ts=" + ts.getTime();
      } else {
        url = url + "&_ts=" + ts.getTime();
      };

      this.url = url;
      this.async = mode;

      this.xmlhttp.open(method, url, mode);
      this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    },

    send: function(data) {
      this.sent = data;

      this.xmlhttp.send(data);

      // There's a difference in FF and IE behavior:
      // IE calls onreadystatechange even foe non-async requests,
      // while FF doesn't; thus, the following condition a 
      // a workaround for FF behavior

      if (!this.async && !this.onsuccesscalled && this.xmlhttp.readyState == 4) {
        this.responseXML  = this.xmlhttp.responseXML;
        this.responseText = this.xmlhttp.responseText;
        this.onsuccesscalled = true;
        if (this.onsuccess) {
          this.onsuccess();
        };
      };
    },
    
    handleError: function(callbacks) { 
      // FireFox bug workaround;
      // sometimes FF (up to 1.5.0.1) XMLHTTPRequest object 
      // returns empty response body whatever the actual response was 
      // (when calling from the FCKEditor event handler).

      if (this.xmlhttp.responseText == "" && this.xmlhttp.responseXML == null) {
        return false;
      };

      if (!this.xmlhttp.responseXML) {
        alert("Error; server responded with '"+this.xmlhttp.responseText+"'");
        return true;
      };

      if (!this.xmlhttp.responseXML.documentElement) {
        alert("Error; server responded with '"+this.xmlhttp.responseText+"'");
        return true;
      };

      if (this.xmlhttp.responseXML.documentElement.tagName == "parsererror") {
        alert("Error; server responded with '"+this.xmlhttp.responseText+"'");
        return true;
      };

      var root = this.xmlhttp.responseXML.documentElement;
      if (root.tagName == 'error') {
        var handler = null;
        var code = root.getAttribute('code');
        var text = root.text ? root.text : root.textContent;

        if (callbacks != null) {
          handler = callbacks[code];
        };

        if (handler) {
          return handler(code, text);
        } else {
          var query_text = this.sent.replace(/&/g, "\n");
          alert("ERROR: " + code + " " + text + "\n" + query_text);
          return true;
        };
      };

      return false;
    }
  } 
};

var page = new Object();
page._listeners = [];
page._cities = [];
page._citiesOrdered = [];
page._currentCity = null;
page._ignoredParams = { 'id' : 1, 'Biggest city' : 1 };
page._checkedCity = null;

page.setCheckedCity = function(cityId) {
  this._checkedCity = cityId;
}

page.getCheckedCity = function() {
  return this._checkedCity;
}

page.addCity = function(city) {
  this._cities[city.id] = city;
  this._citiesOrdered.push(city);
}

page.addListener = function(event, listener) {
  if (!this._listeners[event]) {
    this._listeners[event] = [];
  };
  this._listeners[event].push(listener);
}

page.callListeners = function(event) {
  var listeners = this._listeners[event];
  for (var i=0; i<listeners.length; i++) {
    listeners[i]();
  };
}

page.getCity = function(id) {
  return this._cities[id];
}

page.getCurrentCity = function() {
  return this._currentCity;
}

page.getCurrentLocationNameBlock = function() {
  if (this.getCheckedCity() != null) {
    return $('location-name-2');
  } else {
    return $('location-name-1');
  };
}

page.getCurrentDataBlock = function() {
  if (this.getCheckedCity() != null) {
    return $('data-2');
  } else {
    return $('data-1');
  };
}

page.doHideCity = function(cityId) {
  var city = this.getCity(cityId);

  if (city.id != this.getCheckedCity()) {
    this.getCurrentDataBlock().innerHTML = '';

    for (var i=0; i<city.dots.length; i++) {
      show_dot('dot'+(i+1), 'hidden', city.dots[i].ypoint, city.dots[i].xpoint);
    };
    $('map-mask-'+city.id.toString()).style.visibility = 'hidden';
  };
}

page.hideCity = function() {
  var city = this.getCurrentCity();

  if (city) {
    this.doHideCity(city.id);
  };

  this.setCurrentCity(null);
}

page.onLoad = function() {
  this.callListeners('after-load');
}

page.onLoadShowCityListener = function(id) {
  page.showCity(id);
}

page.preloadImages = function() {
  for (var i=0; i<this._citiesOrdered.length; i++) {
    var city = this._citiesOrdered[i];
    city._image = new Image;
    city._image.src = 'image/tm_map'+city.id.toString()+'.gif';
  };
}

page.setCurrentCity = function(city) {
  this._currentCity = city;
}

page.showCity = function(id) {
  this.hideCity();

  var city = page.getCity(id);
  this.setCurrentCity(city);

  this.getCurrentLocationNameBlock().innerHTML = city.ename;

  var orderBy = $('sidebar-orderby-field').innerHTML;

  this.getCurrentDataBlock().innerHTML = '';
  for (var i in city.params) {
    if (!this._ignoredParams[i]) {
      if (i == orderBy) {
        this.getCurrentDataBlock().innerHTML += '<div><span class="property-name orderby">'+ i + '&nbsp;:</span> <span class="property-value orderby">' + city.params[i] + '</span></div>';
      } else {
        this.getCurrentDataBlock().innerHTML += '<div><span class="property-name">'+ i + '&nbsp;:</span> <span class="property-value">' + city.params[i] + '</span></div>';
      };
    };
  };
//  this.getCurrentDataBlock().innerHTML += '<a href="http://tealit.com/ad_categories.php?content_mode=2&section_id=29&search_condition=upper(%60city%60)%20like%20\'%'+city.ename.toUpperCase()+'%\'">Jobs</a><br/>';
  this.getCurrentDataBlock().innerHTML += '<a class="piclink" href="city_image.php?city_id='+city.id+'">Pictures</a><br/>';
  

  for (var i=0; i<city.dots.length; i++) {
    var dot = city.dots[i];
    show_dot('dot'+(i+1), 'visible', dot.ypoint, dot.xpoint);
  };

  var image_name = 'image/tw_map' + city.id + '.gif';
  $('map-mask-'+id.toString()).style.visibility = 'visible';
}

page.onUpdateSort = function(sortbox, eng_checked) {
	var system;
	if (eng_checked)
		system = "english";
	else
		system = "metric";
	sortbox.blur();
	window.focus();
	this.doUpdateSort(sortbox.value, system);
}

page.onUpdateSystem = function(system, sort) {
  if (system == 'english') {
    document.location.href = 'index.php?nonmetric=1&select='+sort;
  } else if (system == 'metric') {
    document.location.href = 'index.php?select='+sort;
  };
}

page.doUpdateSort = function(sortmode, system) {
  $('sidebar-content').style.display = 'none';
  $('sidebar-loading').style.display = 'block';

  var request = createXMLHttpRequest();
  if (system == 'english') {
    request.open('GET', 'sidebar.php?nonmetric=1&select='+sortmode, 1);
  } else {
    request.open('GET', 'sidebar.php?select='+sortmode, 1);
  };
  request.onsuccess = function() { page.onSidebarUpdated(request.responseText); };
  request.send('');
}

page.onSidebarUpdated = function(content) {
  $('sidebar-loading').style.display = 'none';
  $('sidebar-content').style.display = 'block';

  $('layout-cell-sidebar-wrapper').innerHTML = content;
  
  var cityId = parseInt($('sidebar-first-city-id').innerHTML);
  this.showCity(cityId);
}

page.onCheckChange = function(cityId) {
  var checked = $('check-'+cityId).checked;

  if (checked) {
    this.doCheckSelect(cityId);
  } else {
    this.doCheckClear();
  };
}

page.doCheckClear = function() {
  for (var i=0; i<this._citiesOrdered.length; i++) {
    var city = this._citiesOrdered[i];
    $('check-'+city.id.toString()).checked = false;
  };
  var checkedCity = this.getCheckedCity();

  if (checkedCity != null) {
    this.doHideCity(checkedCity);
  };

  this.setCheckedCity(null);

  if (checkedCity != null) {
    this.doHideCity(checkedCity);
  };

  this.hideComparisonBlock();
}

page.doCheckSelect = function(cityId) {
  this.doCheckClear();
  $('check-'+cityId.toString()).checked = true;
  this.showCity(cityId);
  this.setCheckedCity(cityId);

  this.showComparisonBlock();
}

page.hideComparisonBlock = function() {
  $('info-block-2').style.visibility = 'hidden';
}

page.showComparisonBlock = function() {
  $('info-block-2').style.visibility = 'visible';
}

page.addListener('after-load', function() { page.preloadImages() });