
var GoogleMapUtils = {

  icons: {},

  load: function() {
    //Prevent error message
    if (typeof (google.maps.Icon) == "undefined") return;
  
    GoogleMapUtils.icons = GoogleMapUtils.getIcons();
  },

  // Determine whether gMaps will work in the browser and set a classname if it won't
  isImplemented: function(canvasEl) {
    var isImplemented = google.maps.BrowserIsCompatible();

    if (!isImplemented)
      Spif.ClassNameAbstraction.add(document.body, "incompatibleBrowser");

    return canvasEl != null && isImplemented;
  },

  // Set minimum and maximum zoom
  setMinMaxZoom: function(minZoom, maxZoom) {
    G_PHYSICAL_MAP.getMinimumResolution = function() { return minZoom; };
    G_NORMAL_MAP.getMinimumResolution = function() { return minZoom; };
    G_SATELLITE_MAP.getMinimumResolution = function() { return minZoom; };
    G_HYBRID_MAP.getMinimumResolution = function() { return minZoom; };

    G_PHYSICAL_MAP.getMaximumResolution = function() { return maxZoom; };
    G_NORMAL_MAP.getMaximumResolution = function() { return maxZoom; };
    G_SATELLITE_MAP.getMaximumResolution = function() { return maxZoom; };
    G_HYBRID_MAP.getMaximumResolution = function() { return maxZoom; };
  },

  // Get the correct cluster icon determined by the given count
  getClusterIconByCount: function(count, hasDetail) {
    var icons = GoogleMapUtils.icons.clusters;
    var icon = null;
    switch (true) {
      case count < 10:
        if (hasDetail)
          icon = icons[4];
        else
          icon = icons[0];
        break;
      case count < 50:
        if (hasDetail)
          icon = icons[5];
        else
          icon = icons[1];
        break;
      case count < 500:
        icon = icons[2];
        break;
      default:
        icon = icons[3];
        break;
    }
    return icon;
  },

  // Get the correct icon determined by the given type
  getPointIconByType: function(type, size) {
    var icons = null;
    var isSelectcamp = (resources.isselectcamp.toLowerCase() == 'true');

    if (GoogleMapUtils.icons.accopins == null) {
      GoogleMapUtils.icons = GoogleMapUtils.getIcons();
    }

    switch (size) {
      case 1:
        icons = GoogleMapUtils.icons.accopins;
        break;
      default:
        icons = GoogleMapUtils.icons.pins;
        break;
    }

    var icon = null;
    switch (type.toLowerCase()) {
      case "vakantiepark":
        icon = icons[1];
        break;
      case "camping":
        icon = isSelectcamp ? icons[3] : icons[2];
        break;
      case "hotel":
        icon = icons[0];
        break;
      case "huis/villa":
      default:
        icon = isSelectcamp ? icons[2] : icons[3];
        break;
    }
    return icon;
  },

  // Return the predefined custom icons for VS, including pins and clusters
  getIcons: function() {
    var icons = [];
    var colours = ["brown", "green", "orange", "red"]; // brown = huis, green = vakantiepark, orange = camping, red = hotel
    var types = ["cart", "tree", "bed", "camera", "cutlery"];

    // VS logo
    var icon = new google.maps.Icon();
    icon.image = "/img/pin-blue-big.png";
    icon.iconSize = new google.maps.Size(28, 37);
    icon.iconAnchor = new google.maps.Point(19, 37);
    icon.shadow = "/img/pin-big-shadow.png";
    icon.shadowSize = new google.maps.Size(33, 37);
    icons.VSicon = icon;

    // acco pins
    icons.accopins = [];
    for (var i = 0; i < colours.length; i++) {
      icon = new google.maps.Icon();
      icon.image = "/img/pin-" + colours[i] + "-big.png";
      icon.iconSize = new google.maps.Size(28, 37);
      icon.iconAnchor = new google.maps.Point(19, 37);
      icon.shadow = "/img/pin-big-shadow.png";
      icon.shadowSize = new google.maps.Size(35, 37);
      icons.accopins.push(icon);
    }

    // pins
    icons.pins = [];
    for (var i = 0; i < colours.length; i++) {
      icon = new google.maps.Icon();
      icon.image = "/img/pin-" + colours[i] + "-small.png";
      icon.iconSize = new google.maps.Size(18, 25);
      icon.iconAnchor = new google.maps.Point(9, 25);
      icon.shadow = "/img/pin-small-shadow.png";
      icon.shadowSize = new google.maps.Size(23, 25);
      icons.pins.push(icon);
    }

    // points of interest
    icons.poi = [];
    for (var i = 0; i < types.length; i++) {
      icon = new google.maps.Icon();
      icon.image = "/img/circle-" + types[i] + ".png";
      icon.iconSize = new google.maps.Size(29, 29);
      icon.iconAnchor = new google.maps.Point(14, 29);
      icon.shadow = "/img/circle-medium-shadow.png";
      icon.shadowSize = new google.maps.Size(35, 27);
      icons.poi.push(icon);
    }

    // clusters
    icons.clusters = [];
    var smallIcon = new google.maps.Icon();
    smallIcon.image = "/img/circle-small.png";
    smallIcon.iconSize = new google.maps.Size(21, 21);
    smallIcon.iconAnchor = new google.maps.Point(10, 21);
    smallIcon.shadow = "/img/circle-small-shadow.png";
    smallIcon.shadowSize = new google.maps.Size(25, 20);
    icons.clusters.push(smallIcon);

    var mediumIcon = new google.maps.Icon();
    mediumIcon.image = "/img/circle-medium.png";
    mediumIcon.iconSize = new google.maps.Size(29, 29);
    mediumIcon.iconAnchor = new google.maps.Point(14, 29);
    mediumIcon.shadow = "/img/circle-medium-shadow.png";
    mediumIcon.shadowSize = new google.maps.Size(35, 27);
    icons.clusters.push(mediumIcon);

    var largeIcon = new google.maps.Icon();
    largeIcon.image = "/img/circle-large.png";
    largeIcon.iconSize = new google.maps.Size(38, 38);
    largeIcon.iconAnchor = new google.maps.Point(19, 38);
    largeIcon.shadow = "/img/circle-large-shadow.png";
    largeIcon.shadowSize = new google.maps.Size(48, 37);
    icons.clusters.push(largeIcon);

    var hugeIcon = new google.maps.Icon();
    hugeIcon.image = "/img/circle-huge.png";
    hugeIcon.iconSize = new google.maps.Size(49, 49);
    hugeIcon.iconAnchor = new google.maps.Point(24, 49);
    hugeIcon.shadow = "/img/circle-huge-shadow.png";
    hugeIcon.shadowSize = new google.maps.Size(65, 46);
    icons.clusters.push(hugeIcon);

    var smallIcon2 = new google.maps.Icon();
    smallIcon2.image = "/img/circle-small2.png";
    smallIcon2.iconSize = new google.maps.Size(21, 21);
    smallIcon2.iconAnchor = new google.maps.Point(10, 21);
    smallIcon2.shadow = "/img/circle-small2-shadow.png";
    smallIcon2.shadowSize = new google.maps.Size(25, 20);
    icons.clusters.push(smallIcon2);

    var mediumIcon2 = new google.maps.Icon();
    mediumIcon2.image = "/img/circle-medium2.png";
    mediumIcon2.iconSize = new google.maps.Size(29, 29);
    mediumIcon2.iconAnchor = new google.maps.Point(14, 29);
    mediumIcon2.shadow = "/img/circle-medium2-shadow.png";
    mediumIcon2.shadowSize = new google.maps.Size(35, 27);
    icons.clusters.push(mediumIcon2);

    return icons;
  },

  // gets ClusterIsland (Binnen de XML in de HTML Pagina)
  getClusterIsland: function(coordsEl) {
    var xmlIsland = coordsEl.getElementsByTagName('xml')[0];
    return xmlIsland.XMLDocument ? xmlIsland.XMLDocument.documentElement : xmlIsland.firstChild;
  },

  // Pakt de clusters in het clusterIsland
  getClusters: function(coordsEl) {
    return GoogleMapUtils.getClusterIsland(coordsEl).getElementsByTagName('cluster');
  },

  // Pakt de clusters tag in het clusterIsland
  getClustersTag: function(coordsEl) {
    return GoogleMapUtils.getClusterIsland(coordsEl);
  },

  // Load markers onto mapObj, using coordsEl as the source information
  loadMarkers: function(mapObj, coordsEl, fromResultmap) {
    var clusters = GoogleMapUtils.getClusters(coordsEl);
    var marker, cluster, latlng, icon, isMultiple, type, count, size, detail, name;

    for (var i = 0; i < clusters.length; i++) {
      cluster = clusters[i];
      latlng = new google.maps.LatLng(cluster.getAttribute("lat"), cluster.getAttribute("lng"));
      count = cluster.getAttribute('count');
      isMultiple = count > 1;

      /* hier gaat nog niet goed in FF */
      if (!isMultiple && cluster.getElementsByTagName('type').length > 0) {
        type = cluster.getElementsByTagName('type')[0].firstChild.nodeValue.toLowerCase();
        name = cluster.getElementsByTagName('name')[0].firstChild.nodeValue;
        icon = GoogleMapUtils.getPointIconByType(type, 0);
        marker = new google.maps.Marker(latlng, { icon: icon, title: name });
        google.maps.Event.addListener(marker, "click", mapObj.handleMarkerClick);

        var markerArray = mapObj.markers[type];
        if (!markerArray) {
          markerArray = mapObj.markers[type] = [];
        }
        markerArray.push(marker);
        mapObj.markers[type].push(marker);
      }
      else {
        size = GoogleMapUtils.getSizeByCount(count);
        detail = cluster.getAttribute("detail");

        if (detail == 'true') {
          icon = GoogleMapUtils.getClusterIconByCount(count, true);
          marker = new LabeledMarker(latlng, {
            icon: icon,
            clickable: true,
            draggable: false,
            labelText: count,
            labelOffset: size
          });
          google.maps.Event.addListener(marker, "click", mapObj.handleClusterClick);
        }
        else {
          icon = GoogleMapUtils.getClusterIconByCount(count, false);
          marker = new LabeledMarker(latlng, {
            icon: icon,
            clickable: fromResultmap,
            draggable: false,
            labelText: count,
            labelOffset: size
          });
          if (fromResultmap) google.maps.Event.addListener(marker, "click", mapObj.handleLargeClusterClick);
        }
      }

      marker.VSpoint = cluster; // blegh! set a custom attribute on the marker to keep track of the acc info 
      mapObj.map.addOverlay(marker);
    }
  },

  // Load total
  loadTotal: function(mapObj, coordsEl) {
    var cluster = GoogleMapUtils.getClustersTag(coordsEl);
    var total = cluster.getAttribute("totalCount");
    if (total == null) total = 0;
    var header = document.getElementById('results-header');
    if (header) {
      var countElem = header.getElementsByTagName('H2')[0];
      var countText = countElem.innerHTML;
      countElem.innerHTML = total + countText.substring(countText.indexOf('&nbsp;'));
    }
  },

  // Figure out what bounds to draw the map at by default
  getMapDefaultView: function(coordsEl, useCoordinates) {
    var googleMapBounds = window.location.href.match('[&|\?]google-map-bounds=(.*?)&');
    var bounds, sw, ne;
    if (!useCoordinates && googleMapBounds && googleMapBounds[1] && googleMapBounds[1].indexOf(",") != -1) {
      bounds = unescape(googleMapBounds[1]).split(",");
      sw = new google.maps.LatLng(bounds[0], bounds[1]);
      ne = new google.maps.LatLng(bounds[2], bounds[3]);
    }
    else {
      sw = GoogleMapUtils.getMinLatLng(coordsEl);
      ne = GoogleMapUtils.getMaxLatLng(coordsEl);
    }

    return new google.maps.LatLngBounds(sw, ne);
  },

  // Fetch min latlng for the displayed clusters
  getMinLatLng: function(coordsEl) {
    var clusters = GoogleMapUtils.getClusterIsland(coordsEl);
    var minLat = clusters.getAttribute("minLat");
    var minLng = clusters.getAttribute("minLng");
    return new google.maps.LatLng(minLat, minLng);
  },

  // Fetch max latlng for the displayed clusters
  getMaxLatLng: function(coordsEl) {
    var clusters = GoogleMapUtils.getClusterIsland(coordsEl);
    var maxLat = clusters.getAttribute("maxLat");
    var maxLng = clusters.getAttribute("maxLng");
    return new google.maps.LatLng(maxLat, maxLng);
  },

  // Figure out what zoom level to draw the map at by default
  getDefaultZoom: function(map, rect) {
    var googleMapZoom = window.location.href.match('[&|\?]google-map-zoom=([^&]*)&');
    if (googleMapZoom && googleMapZoom[1]) {
      var zoomLevel = parseInt(googleMapZoom[1]);
      if (zoomLevel >= 4)
        return zoomLevel;
    }
    return map.getBoundsZoomLevel(rect);
  },

  // Return the correct size for a Cluster icon depending on how the count of accommodations displayed in it
  getSizeByCount: function(count) {
    var size;
    switch (true) {
      case count < 10:
        size = new google.maps.Size(-2, -17);
        break;
      case count < 50:
        size = new google.maps.Size(-6, -21);
        break;
      case count < 85:
        size = new google.maps.Size(-6, -25);
        break;
      case count < 500:
        size = new google.maps.Size(-9, -25);
        break;
      default:
        size = new google.maps.Size(-9, -30);
        break;
    }
    return size;
  }
};

// A generic wrapper object to create our info windows
// This class is extended by each specific implementation depending on requirements
var GoogleMapInfoWindow = function(pos, infoWindowId) {
  this.init(pos, infoWindowId);
}

GoogleMapInfoWindow.prototype = {

  el: null,
  container: null,
  
  init: function(pos, infoWindowId)
  {
    if (!pos || !infoWindowId) return;
    this.el = document.getElementById(infoWindowId);
    this.container = document.getElementById(infoWindowId + 'Container');
    this.setPosition(pos);
  },

  show: function()
  {
    Spif.ClassNameAbstraction.replace(this.container, "hideInfoWindow", "showInfoWindow");
  },
  
  hide: function()
  {
    Spif.ClassNameAbstraction.replace(this.container, "showInfoWindow", "hideInfoWindow");
  },
  
  isHidden: function()
  {
    return Spif.ClassNameAbstraction.contains(this.container, "hideInfoWindow");
  },
  
  setPosition: function(pos)
  {
    this.container.style.top = pos.y + 'px';
    this.container.style.left = pos.x + 'px';
  }
};
