//___________________ Globals

var buildings = new Array();
var pois = new Array();
var filtersettings = new Object;
var map;
var geocoder;
var geocoderCountry = "Austria";
var umkreisPoly;
var initialAddress = "Wien, Österreich";
var startPos;
var startPosMarker;
var isStartPosValid = false;
var umkreisPoly;
var aufAnfrageLink = "<a href='javascript:void(0);'>auf Anfrage</a>";
var aufAnfrageHeader = "<tr id='aufanfrageheader'><td colspan='5'>Freie Flächen auf Anfrage:</td></tr>";
var facets;
var labelObjektgroesse;
var searchMode;
var url;
var params;
var baseSearchUrl = "http://www.kgal.at/de/offices/objektsuche/";
var filtersettingsAnchorString = "";

filtersettings.objektgroesse = 200;
filtersettings.umkreis = 25;


//___________________ General JS

function filter() {
  var northest = -90;
  var southest = 90;
  var eastest = -180;
  var westest = 180;
  var lat;
  var lng;
  
  facets = new Facets();

  for (var i=0; i < buildings.length; i++) {  
    
    var valid = true;
    var b = buildings[i];
        
    valid = valid && (!filtersettings.nutzungsart || filtersettings.nutzungsart == b.nutzungsart);
    valid = valid && (!filtersettings.lage || filtersettings.lage == b.lage);
    valid = valid && (!filtersettings.verkehrsanbindung || filtersettings.verkehrsanbindung == b.verkehrsanbindung);
    valid = valid && (!isStartPosValid || filtersettings.umkreis > b.distanceToStartPos)

    b.setVisible(valid);
    
    if (valid) {
      facets.add(b);
      
      if (b.position) {
        lat = b.position.lat();
        if (lat < westest)
          westest = lat;
        if (lat > eastest)
          eastest = lat;
          
        lng = b.position.lng();
        if (lng < southest)
          southest = lng;
        if (lng > northest)
          northest = lng;
      }
    }
  }
  
  if (searchMode == "home")
    updateFilterUrlParams();
  updateFiltersWithFacets();
  
  
  //Zoom map according to visible buildings.
  if (lat && lng)
    map.fitBounds(new google.maps.LatLngBounds(
      new google.maps.LatLng(westest, southest), //south west
      new google.maps.LatLng(eastest, northest)  //north east
    ));
}

function finalize() {
  //Do everything that can't be done until all buildings' positions are set.
  switch (searchMode) {
    case "home":
      filter();
      filterOnlyAufAnfrage();
      break;
      
    case "overview":    
      fitBounds();
      break;
      
    case "search":
      initialSort();
      if (params) {
        for (var i = 0; i < buildings.length; i++)
          buildings[i].addTableEntry("none");
        setFacetParams(params);
      }
      else {
        for (var i = 0; i < buildings.length; i++)
          buildings[i].addTableEntry("block");
        filter();
      }
        
      filterOnlyAufAnfrage();        
      break;
  }
}

function finalizePois() {
  $("select#poi").html("<option value=''>Beliebig</option>");
  for (var i = 0; i < pois.length; i++) {
    
    $("select#poi").append("<option value='" + pois[i].address + "'>" + pois[i].name + "</option>");
  }
}

function updateFilterUrlParams() {
  filtersettingsAnchorString = "#filter:nutzungsart=" + encodeURI(filtersettings.nutzungsart) +
                 "&lage=" + encodeURI(filtersettings.lage) +
                 "&objektgroesse=" + encodeURI(filtersettings.objektgroesse) + 
                 "&verkehrsanbindung=" + encodeURI(filtersettings.verkehrsanbindung) +
                 "&poi=" + encodeURI(filtersettings.poi) +
                 "&umkreis=" + encodeURI(filtersettings.umkreis);
                 
  //document.searchparams.action = "de/offices/objektsuche/" + filtersettingsAnchorString
  //$("#searchparams").attr("action", "de/offices/objektsuche/" + filtersettingsAnchorString);
  //alert($("#searchparams").attr("action"));//html());   
}

function updateFiltersWithFacets(init) {
  var selected;
  
  //Nutzungsart
  $("select#nutzungsart").html("<option value=''>Beliebig</option>");
  for (var i = 0; i < facets.nutzungsart.length; i++) {
    selected = facets.nutzungsart[i] == filtersettings.nutzungsart ? "selected = 'selected'" : "";
    if (selected) {
      $("#searchparams input#clearNutzungsart").attr("checked", "checked").removeAttr("disabled");
      $("select#nutzungsart").attr("disabled", "disabled");
    }
    $("select#nutzungsart").append("<option " + selected + " value='" + facets.nutzungsart[i] + "'>" + facets.nutzungsart[i] + "</option>");
  }
  
  //Lage
  $("select#lage").html("<option value=''>Beliebig</option>");
  for (var i = 0; i < facets.lage.length; i++) {
    selected = facets.lage[i] == filtersettings.lage ? "selected = 'selected'" : "";
    if (selected) {
      $("#searchparams input#clearLage").attr("checked", "checked").removeAttr("disabled");
      $("select#lage").attr("disabled", "disabled");
    }
    $("select#lage").append("<option " + selected + " value='" + facets.lage[i] + "'>" + facets.lage[i] + "</option>");
  }
  
  //Verkehrsanbindung
  $("select#verkehrsanbindung").html("<option value=''>Beliebig</option>");
  for (var i = 0; i < facets.verkehrsanbindung.length; i++) {
    selected = facets.verkehrsanbindung[i] == filtersettings.verkehrsanbindung ? "selected = 'selected'" : "";
    if (selected) {
      $("#searchparams input#clearVerkehrsanbindung").attr("checked", "checked").removeAttr("disabled");
      $("select#verkehrsanbindung").attr("disabled", "disabled");
    }
    $("select#verkehrsanbindung").append("<option " + selected + " value='" + facets.verkehrsanbindung[i] + "'>" + facets.verkehrsanbindung[i] + "</option>");
  }
  
  //POI
  $("select#poi").html("<option value=''>Beliebig</option>");
  for (var i = 0; i < pois.length; i++) {
    selected = pois[i].address == filtersettings.poi ? "selected = 'selected'" : "";
    if (selected) {
      $("#searchparams input#clearPoi").attr("checked", "checked").removeAttr("disabled");
      $("select#poi").attr("disabled", "disabled");
    }
    $("select#poi").append("<option " + selected + " value='" + pois[i].address + "'>" + pois[i].name + "</option>");
  }
}

function filterOnlyAufAnfrage() {
  for (var i=0; i < buildings.length; i++) {
    var b = buildings[i];
      
    if (filtersettings.objektgroesse > b.freeArea) {
      $("#results > tbody > tr#buildingID" + b.id + " > .colfreearea div").addClass("auf-anfrage");
      b.setAufAnfrage(true);
    }
    else {
      $("#results > tbody > tr#buildingID" + b.id + " > .colfreearea div").removeClass("auf-anfrage");
      b.setAufAnfrage(false);
    }
  }
    
  //Insert <tr>-Separator between "auf Anfrage" and regular entries.
  $("#results #aufanfrageheader").remove();  //Remove old separator at first.
  $("#results > tbody > tr:has('div.auf-anfrage'):first").before(aufAnfrageHeader);
}

function onMouseOverDetail(base) {
  //$(this).addClass("selected");
  $("td.coladdr .details", base).slideDown(200);
  $("td.colimg > div", base).stop().animate({height: "120px"}, 250);
  $("td:not('.colimg') > div", base).stop().animate({height: "106px"}, 250);
}

function onMouseOutDetail(base) {
  //$(this).removeClass("selected");
  $("td.coladdr .details", base).slideUp(200);
  $("td.colimg > div", base).stop().animate({height: "60px"}, 250);
  $("td:not('.colimg') > div", base).stop().animate({height: "46px"}, 250);
}

function initialSort() {
  $("#results tbody").empty();  //Empty placeholder table content (necessary for W3C validation).
  
  buildings.sort(SpecialBuildingSort);
}

function SpecialBuildingSort(a, b) {
  if (a.freeArea > 0 && b.freeArea > 0)
    return b.freeArea - a.freeArea;
  else if (a.freeArea > 0 && b.freeArea == 0)
    return -1;
  else if (a.freeArea == 0 && b.freeArea > 0)
    return 1;
  else
    return a.postcode - b.postcode;
}

function formatNumber(n) {
  var nStr = new String(n);
  var formatted = new String();
  
  for (var i = 0; i < nStr.length; i++) {
    if (i > 0 && i % 3 == 0)
      formatted = "." + formatted;
    formatted = nStr.charAt(nStr.length - i - 1) + formatted;
  }

  return formatted;
}

function setStartPos(address) {
  if (geocoder) {  
    geocoder.geocode( { 'address': address, 'country': geocoderCountry}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        startPos = results[0].geometry.location;
        startPosMarker.setMap(map);
        startPosMarker.setPosition(startPos);
        isStartPosValid = true;
        
        $("fieldset.umkreis .slider").slider('enable');
         
        map.setCenter(startPos);
        drawUmkreis();
        updateAllDistancesToStartPos();
      }
      else {
        startPos = null;
        startPosMarker.setMap(null);
        isStartPosValid = false;
        
        $("fieldset.umkreis .slider").slider('disable');
        
        umkreisPoly.setMap(null);
      }
      filter();
    });
    }
}

function setFacetParams(params) {
  var p = params.split("&");
  
  //filtersettings durchlaufen und setzen.
  for (var i = 0; i < p.length; i++) {
    var attribute = p[i].split("=")[0];
    var value = p[i].split("=")[1];
    
    if (value && value != "null" && value != "undefined") {
      if (attribute == "objektgroesse" || attribute == "umkreis")
        filtersettings[attribute] = parseFloat(decodeURI(value));
      else
        filtersettings[attribute] = decodeURI(value);
    }
  }
  
  if (false)
    alert(
    "Nutzungsart: " + filtersettings.nutzungsart + "\n" + 
    "Lage: " + filtersettings.lage + "\n" + 
    "Objektgröße: " + filtersettings.objektgroesse + "\n" + 
    "Verkehrsanbindung: " + filtersettings.verkehrsanbindung + "\n" + 
    "POI: " + filtersettings.poi + "\n" + 
    "Umkreis: " + filtersettings.umkreis);

  //GUI Elemente updaten.
  $("fieldset.objektgroesse .slider").slider("value", filtersettings.objektgroesse);
  $("fieldset.umkreis .slider").slider("value", filtersettings.umkreis);
  setStartPos(filtersettings.poi);
}

function updateAllDistancesToStartPos() {
  for (var i=0; i < buildings.length; i++) {    
    buildings[i].updateDistanceToStartPos();
  }
}

function closeAllInfoWindows() {
  for (var i=0; i < buildings.length; i++) {    
    buildings[i].infoWindow.close();
  }
}

function drawUmkreis() {
  var radius = filtersettings.umkreis;
  var latConv = distHaversine(startPos, new google.maps.LatLng(startPos.lat() + 0.1, startPos.lng())) * 10;
  var lngConv = distHaversine(startPos, new google.maps.LatLng(startPos.lat(), startPos.lng() + 0.1)) * 10;

  var vertices = new Array();
  var x = startPos.lat();
  var y = startPos.lng();
  
  for (var start = 0, end = Math.PI * 2; start < end; start += Math.PI / 30)
    vertices.push(new google.maps.LatLng(Math.cos(start) * radius/latConv + x, Math.sin(start) * radius/lngConv + y));
  
  //Now overridden by general zoom-on-visible-buildings
  /*var rectObj = new google.maps.LatLngBounds(
    new google.maps.LatLng(x - radius/latConv, y - radius/lngConv), 
    new google.maps.LatLng(x + radius/latConv, y + radius/lngConv)
  );

  map.fitBounds(rectObj);*/
  
  umkreisPoly.setPath(vertices);
  umkreisPoly.setMap(map);
}

function initializeSearch() {
  labelObjektgroesse = "Objektgröße: ";
  searchMode = "search";

  geocoder = new google.maps.Geocoder();

  if (geocoder) {
    
    geocoder.geocode( { 'address': initialAddress, 'country': geocoderCountry}, function(results, status) {

          if (status == google.maps.GeocoderStatus.OK) {

        var myOptions = {
          zoom: 9,
          center: results[0].geometry.location,
          backgroundColor: "#ffffff",
          mapTypeId: google.maps.MapTypeId.TERRAIN,
          navigationControlOptions: {
            style: google.maps.NavigationControlStyle.ZOOM_PAN
          }, 
          mapTypeControl: false,
          scaleControl: false
        };
      
          map = new google.maps.Map(document.getElementById("map"), myOptions);
          
          //Instantiate startPosMarker
          startPosMarker = new google.maps.Marker({map: map, position: null, icon: "fileadmin/tmpl/standort.png"});
          startPosMarker.setZIndex(9999);
          
          //Instantiate umkreisPoly
          umkreisPoly = new google.maps.Polygon({paths: [new google.maps.LatLng(0, 0)], strokeColor: "#37a2e0", strokeWeight: 1, strokeOpacity: .8, fillColor: "#37a2e0", fillOpacity: 0.1});
          
          //Parse URL and optional anchor-parameters.
          url = self.location.href.split("index.php")[0].split("#")[0].split("?")[0];
          params = self.location.href.split("#filter:")[1];
          if (params) {
            // alert("TEST");
          } else {
            params = self.location.href.split("%23filter%3A")[1];           
          }
            
          //Get JSON Buildings
        $.getJSON(url + "buildings.json",
          function(data){
            $.each(data.buildings, function(i, building){    
              var b = new Building(building, searchMode);
              buildings.push(b);
            });
            finalize();
          }
        );
        
        //Get JSON POIs
        $.getJSON(url + "pois.json",
          function(data){
            $.each(data.pois, function(i, poi){
              var p = new Poi(poi.bezeichnung, poi.adresse);
              pois.push(p);
            });
            finalizePois();
          }
        );
      }
    });
  }
}

function initializeSearchHome() {
  labelObjektgroesse = "Größe: ";
  searchMode = "home";

  geocoder = new google.maps.Geocoder();

  if (geocoder) {
    
    geocoder.geocode( { 'address': initialAddress, 'country': geocoderCountry}, function(results, status) {
    
          if (status == google.maps.GeocoderStatus.OK) {

        var myOptions = {
          zoom: 9,
          center: results[0].geometry.location,
          backgroundColor: "#ffffff",
          mapTypeId: google.maps.MapTypeId.TERRAIN,
          navigationControlOptions: {
            style: google.maps.NavigationControlStyle.SMALL
          }, 
          mapTypeControl: false,
          scaleControl: false
        };
      
          map = new google.maps.Map(document.getElementById("map"), myOptions);
          
          //Instantiate startPosMarker
          startPosMarker = new google.maps.Marker({map: map, position: null, icon: "fileadmin/tmpl/standort.png"});
          startPosMarker.setZIndex(9999);
          
          //Instantiate umkreisPoly
          umkreisPoly = new google.maps.Polygon({paths: [new google.maps.LatLng(0, 0)], strokeColor: "#37a2e0", strokeWeight: 1, strokeOpacity: .8, fillColor: "#37a2e0", fillOpacity: 0.1});
          
          //Parse URL and optional anchor-parameters.
          url = self.location.href.split("index.php")[0].split("#")[0].split("?")[0];
          params = "";
          
          //Get JSON Buildings
        $.getJSON(self.location.href.split("index.php")[0]+"buildings.json",
          function(data){
            $.each(data.buildings, function(i, building){  
              var b = new Building(building, searchMode);
              buildings.push(b);
            });
            finalize();
          }
        );
        
        //Get JSON POIs
        $.getJSON(url + "pois.json",
          function(data){
            $.each(data.pois, function(i, poi){
              var p = new Poi(poi.bezeichnung, poi.adresse);
              pois.push(p);
            });
            finalizePois();
          }
        );
      }
    });
  }
}

function initializeSearchOverview() {
  searchMode = "overview";
  
  geocoder = new google.maps.Geocoder();

  if (geocoder) {
    
    geocoder.geocode( { 'address': initialAddress, 'country': geocoderCountry}, function(results, status) {

          if (status == google.maps.GeocoderStatus.OK) {

        var myOptions = {
          zoom: 9,
          center: results[0].geometry.location,
          backgroundColor: "#ffffff",
          mapTypeId: google.maps.MapTypeId.ROADMAP,
          navigationControlOptions: {
            style: google.maps.NavigationControlStyle.DEFAULT
          }, 
          mapTypeControl: true,
          scaleControl: false
        };
        
          map = new google.maps.Map(document.getElementById("map"), myOptions);
         
          //Get JSON Objects
        $.getJSON(self.location.href.split("index.php")[0].split("#")[0]+"buildings.json",
          function(data){
            $.each(data.buildings, function(i, building){
              var b = new Building(building, searchMode);
              buildings.push(b);
              finalize();
            });
          }
        );
      }
    });
  }
}

function fitBounds() {
  var northest = -90;
  var southest = 90;
  var eastest = -180;
  var westest = 180;
  var lat;
  var lng;
  
  for (var i = 0; i < buildings.length; i++) {
    var b = buildings[i];
    if (b.position) {
      lat = b.position.lat();
      if (lat < westest)
        westest = lat;
      if (lat > eastest)
        eastest = lat;
        
      lng = b.position.lng();
      if (lng < southest)
        southest = lng;
      if (lng > northest)
        northest = lng;
    }
  }
  
  //Zoom map according to visible buildings.
  if (lat && lng)
    map.fitBounds(new google.maps.LatLngBounds(
      new google.maps.LatLng(westest, southest), //south west
      new google.maps.LatLng(eastest, northest)  //north east
    ));
}

function rad(x) {
  return x * Math.PI/180;
}

function distHaversine(p1, p2) {
  if (!p1 || !p2)
    return;

  var R = 6371; // earth's mean radius in km
  var dLat  = rad(p2.lat() - p1.lat());
  var dLong = rad(p2.lng() - p1.lng());
  
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  
  return d.toFixed(3);
}


//___________________ jQuery

$(document).ready(function(){

  //Guistuff.
  $("#searchparams .clearfilter").hover(
    function() {
      $(this).css("background-position-y", "bottom");
    },
    function() {
      $(this).css("background-position-y", "top");
    }
  );

  //Facet browsing resetters
  $("#searchparams select").removeAttr("disabled"); //Firefox caching umgehen.
  $("#searchparams input.clearfilter").removeAttr("checked").attr("disabled", "disabled");
  $("#searchparams input#clearNutzungsart").click(function() {
    $(this).removeAttr("checked").attr("disabled", "disabled");
    $("#nutzungsart").removeAttr("disabled");
    filtersettings.nutzungsart = null;
    filter();
  });
  $("#searchparams input#clearLage").click(function() {
    $(this).removeAttr("checked").attr("disabled", "disabled");
    $("#lage").removeAttr("disabled");
    filtersettings.lage = null;
    filter();
  });
  $("#searchparams input#clearVerkehrsanbindung").click(function() {
    $(this).removeAttr("checked").attr("disabled", "disabled");
    filtersettings.verkehrsanbindung = null;
    $("#verkehrsanbindung").removeAttr("disabled");
    filter();
  });
  $("#searchparams input#clearPoi").click(function() {
    $(this).removeAttr("checked").attr("disabled", "disabled");
    filtersettings.poi = null;
    $("#poi").removeAttr("disabled");
    setStartPos(null);
  });
    
  //Filterform elements
  $("#nutzungsart").change(function() {
    filtersettings.nutzungsart = $(this).val();
    filter();
  });
  $("#lage").change(function() {
    filtersettings.lage = $(this).val();
    filter();
  });
  $("fieldset.objektgroesse .slider").slider({ 
    min: 100,
    max: 5000,
    range: "min",
    step: 100,
    value: 100,  
    animate: true,
    slide: function(event, ui) {
      $("fieldset.objektgroesse label").text(labelObjektgroesse + ui.value + "m²");
      filtersettings.objektgroesse = ui.value;
      filterOnlyAufAnfrage();
      if (searchMode == "home")
        updateFilterUrlParams();
    },
    change: function(event, ui) {  
      $("fieldset.objektgroesse label").text(labelObjektgroesse + ui.value + "m²");
    }
  });
  $("#verkehrsanbindung").change(function() {
    filtersettings.verkehrsanbindung = $(this).val();
    filter();
  });
  $("#poi").change(function() {
    filtersettings.poi = $(this).val();
    setStartPos($(this).val());
  });
  
  $("fieldset.umkreis .slider").slider({ 
    min: 1,
    max: 100,
    range: "min",
    step: 1,
    value: 25,  
    animate: true,
    slide: function(event, ui) {  
      $("fieldset.umkreis label").text("Umkreis: " + ui.value + "km");
      filtersettings.umkreis = ui.value;
      if (isStartPosValid) {
        drawUmkreis();
        updateAllDistancesToStartPos();
        filter();
      }
    },
    change: function(event, ui) {  
      $("fieldset.umkreis label").text("Umkreis: " + ui.value + "km");
    }
  });
  $("fieldset.umkreis .slider").slider('disable');
  
  //Formular absenden.
  $("#searchparams input#anzeigen").click(function() {
    window.location = baseSearchUrl + filtersettingsAnchorString;
  });
});
