
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];
        if (xmlIsland.XMLDocument)
            return xmlIsland.XMLDocument.documentElement;
        if (xmlIsland.firstChild)
            return xmlIsland.firstChild;
        // Fix voor IE9 
        var parser = new DOMParser();
        var clusters = parser.parseFromString(xmlIsland.innerHTML, "text/xml");
        return clusters.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';
  }
};

