﻿/* 
* GMap, v0.5.5
* Copyright (c) 2009 Impact Web, Google Inc.
*
* 
* GMap provides an automatic pan and scrolling technique on top of the Google
* maps API. Marker manager is used for visual aids of tour locations.
*
* handleOp and related event chaining code by Tom Horn - www.cannonade.net
*
*/
 
var map;                     	// The Google map used
 
// Variables for operation chaining, leave as is.
var opListCurrent = null;
var opLists = [];
var index = -1;
 
 
///////////////////////
//  MARKER VARIBLES //
/////////////////////
 
// Variables for marker data, leave as is.
var mgr;
var icons = {};
var allmarkers = [];
 
// Width and Height data for all the icons in use.
// Change to suit any changes made to visible icons.
var iconData = {
    "info-shadow": { width: 27, height: 18 },
    "info": { width: 26, height: 26 },
    "iconAKL":{width: 40, height: 44}, 
    "iconWGT":{width: 40, height: 44},      
    "iconKKR":{width: 40, height: 44},      
    "iconCHC":{width: 40, height: 44},      
    "iconQTN":{width: 40, height: 44},      
    "iconDUN":{width: 40, height: 44},      
    "iconFRA":{width: 40, height: 44}, 
    "iconBOI":{width: 40, height: 44} 
};
 
// Data for each custom marker.
// zoom: Min and max level the markers will display in
// places: Array of each marker.
//      - name: Marker name (displayed in title attribute)
//      - icon: Icon to use for [marker, shadow] (from iconData)
//      - iposn: Latitude and Longitude position for the icons position (Its centre)
//      - tourId: The tourId of this tour
var tourMarkerLayer = [
{
    "zoom": [5, 9],
    "places": [
 
      {
          "name": "Auckland",
          "icon": ["iconAKL", "info-shadow"],
          "iposn": [-36.85, 174.75],
          "desc": "AUCKLAND: Tours and Activities from Auckland, New Zealand"
      },
 
      {
          "name": "Wellington",
          "icon": ["iconWGT", "info-shadow"],
          "iposn": [-41.3,174.7833333],
          "desc": "WELLINGTON: Tours and Activities from Wellington, New Zealand"
      },
 
     {
          "name": "Kaikoura",
          "icon": ["iconKKR", "info-shadow"],
          "iposn": [-42.37, 173.67],
          "desc": "KAIKOURA: Spend your day getting close to nature in Kaikoura where mountains meet sea. Kaikoura is world renowned for the variety of marine mammals which can be seen, not least of all the giant sperm whales and the acrobatic Dusky Dolphins"
      },
            {
          "name": "Christchurch",
          "icon": ["iconCHC", "info-shadow"],
          "iposn": [-43.53, 172.61],
          "desc": "CHRISTCHURCH: Welcome to Canterbury, New Zealand. The largest region in the South Island of New Zealand and home to Christchurch, New Zealand's third largest city and international gateway to the rest of the South Island including Queenstown, Wanaka and Milford Sound."
 
      },
 
      {
          "name": "Dunedin",
          "icon": ["iconDUN", "info-shadow"],
          "iposn": [-45.8666667,170.5],
          "desc": "DUNEDIN: Tours and Activities from Dunedin, New Zealand"
      },
 
      {
          "name": "Queenstown",
          "icon": ["iconQTN", "info-shadow"],
          "iposn": [-45.00, 168.70],
          "desc": "QUEENSTOWN: Tours and Activities from Queenstown, New Zealand"
      },
      
      {
          "name": "Franz Joseph",
          "icon": ["iconFRA", "info-shadow"],
          "iposn": [-43.388128, 170.183329],
          "desc": "Franz Joseph and Fox Glaciers: Tours and Activities on the West Coast, New Zealand"
      },
      {
          "name": "Bay of Islands",
          "icon": ["iconBOI", "info-shadow"],
          "iposn": [-35.333333, 174],
          "desc": "Bay of Islands: Tours and Activities above in the Bay of Islands, New Zealand"
      }

/*	{
          "name": "Hanmer Springs",
          "icon": ["info", "info-shadow"],
          "iposn": [-42.55, 172.85],
          "desc": "Here is some test desc"
      },
 
      {
          "name": "Akaroa",
          "icon": ["info", "info-shadow"],
          "iposn": [-43.79, 172.93],
          "desc": "Here is some test desc"
      },
      {
          "name": "Mount Cook",
          "icon": ["info", "info-shadow"],
          "iposn": [-43.76, 170.04],
          "desc": "Here is some test desc"
      },
      {
          "name": "Queenstown",
          "icon": ["info", "info-shadow"],
          "iposn": [-45.03, 168.63],
          "desc": "Here is some test desc"
      },
      {
          "name": "Milford Sound",
          "icon": ["info", "info-shadow"],
          "iposn": [-44.70, 167.90],
          "desc": "Here is some test desc"
      },
      {
          "name": "Arthurs Pass",
          "icon": ["info", "info-shadow"],
          "iposn": [-42.95, 171.58],
          "desc": "Here is some test desc"
      },
*/
    ]
}
];
 
 
/////////////////////////
//  REGIONS VARIABLES //
///////////////////////
 
var operationTimeout = 300; 	// Time in msec between each pan / scroll operation. Lower = faster
 
// Variables for the zoom level and pan locations.
 
//North Island
var topLocation = new GLatLng(-35.8, 174.1);
var topZoomLevel = 7;
var cenLocation = new GLatLng(-38.6833333,176.0833333);
var cenZoomLevel = 7;
var botLocation = new GLatLng(-41.3,174.7833333);
var botZoomLevel = 7;
 
//South Island
var upperLocation = new GLatLng(-41.898188, 172.67761);
var upperZoomLevel = 7;
var midLocation = new GLatLng(-43.145086, 171.868994);
var midZoomLevel = 7;
var lowerLocation = new GLatLng(-45.6, 169.57);
var lowerZoomLevel = 7;
 
//Both Islands
var NILocation = new GLatLng(-38,175);
var NIZoomLevel = 6;
var SILocation = new GLatLng(-44, 170.5);
var SIZoomLevel = 6;
 
 
// Variables for the normal position and zoom level.
var normalLocation = new GLatLng(-41, 172);
var normalZoomLevel = 5;
 
// Region variables
var REGION_MAX_ZOOMLEVEL = 5;           // Max Zoom level polygons are visible on.
var regionClickData = new Array();
var regionVisible = new Array();
 
// Polygon stuff for the regions.
// Data for the polygon overlays
// name: Name of the region
// innercolour: Colour of the inner area of the polygon
// outercolour: Colour of the outter border of the polygon
// panPos: Latitude / Longitude to pan to upon click (Refers to previously set variables)
// zoomLevel: Zoom level to zoom to upon click (Refers to previously set variables)
// points: Points that make up the polygon.
//         Can be as many points as you like as long as they are [lat, long]
//         Last point must equal first point to close off the polygon.
var polyOpacity = 0;
var strokeOpacity = 0;
var regionPolys = [];
var regions = [
{
    "name": "Top North Island",
//  "innercolour": "red",
//  "outercolour": "#89C0FF",
    "panPos": topLocation,
    "zoomLevel": topZoomLevel,
    "points": [[-34, 171], [-34, 175], [-37.5, 180], [-37.5, 172], [-34, 171]]
},
 
{
    "name": "Central North Island",
//  "innercolour": "red",
//  "outercolour": "#89C0FF",
    "panPos": cenLocation,
//    "cursor": pointer,
    "zoomLevel": cenZoomLevel,
    "points": [[-37.5, 172], [-37.5, 180], [-40, 180], [-40, 172], [-37.5, 172]]
},
 
{
    "name": "Bottom North Island",
//  "innercolour": "red",
//  "outercolour": "#89C0FF",
    "panPos": botLocation,
    "zoomLevel": botZoomLevel,
    "points": [[-40, 172], [-40, 180],  [-43, 176], [-40, 172]]
},
 
{
    "name": "Upper South Island",
//  "innercolour": "red",
//  "outercolour": "#89C0FF",
    "panPos": upperLocation,
    "zoomLevel": upperZoomLevel,
    "points": [[-40, 172], [-43, 176], [-42, 168], [-40, 172]]
},
{
    "name": "Middle South Island",
 // "innercolour": "red",
 // "outercolour": "#7BFF47",
    "panPos": midLocation,
    "zoomLevel": midZoomLevel,
    "points": [[-42, 168], [-43, 176], [-45, 173], [-44, 165], [-42, 168]]
},
{
    "name": "Lower South Island",
 //  "innercolour": "red",
 //  "outercolour": "#5972FF",
    "panPos": lowerLocation,
    "zoomLevel": lowerZoomLevel,
    "points": [[-44, 165], [-45, 173], [-48, 172], [-48, 165], [-44, 165]]
}
];
 
 
 
/////////////////
// INITIALISE //
///////////////
 
 
// Initialize function to set up the Google map.
function initialize() {
    if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map_canvas"), { size: new GSize(450,600) });
        map.setMapType(G_NORMAL_MAP);
        //map.disableDragging();
        //map.disableDoubleClickZoom();
        map.enableContinuousZoom();
        map.setCenter(new  GLatLng(-41, 172), 5);
        populateRegions();
        populateListToUpper();
        populateListToLower();
 
        window.setTimeout(setupTourLocations, 0);
 
        GEvent.addListener(map, "zoomend", handleZoomEnd);
        GEvent.addListener(map, "moveend", handleMoveEnd);
    }
}
 
 
 
/////////////////////////
//  MARKER FUNCTIONS //
///////////////////////
 
 
// Methods used for the marker manager and setting it up.
function getIcon(images) {
    var icon = null;
    if (images) {
        if (icons[images[0]]) {
            icon = icons[images[0]];
        } else {
            icon = new GIcon();
            icon.image = "Google/images/" + images[0] + ".png";
            var size = iconData[images[0]];
            icon.iconSize = new GSize(size.width, size.height);
//            icon.iconAnchor = new GPoint(size.width >> 1, size.height >> 1);
            icon.iconAnchor = new GPoint(0,10);
 
            icon.transparent = "/Google/images/transparent.png";
 
            icon.shadow = "/Google/images/" + images[1] + ".png";
            size = iconData[images[1]];
            icon.shadowSize = new GSize(size.width, size.height);
            icons[images[0]] = icon;
        }
    }
    return icon;
}
 
// Methods used for the marker manager and setting it up cont.
function setupTourLocations() {
    mgr = new MarkerManager(map);
    var count = 0;
    allmarkers.length = 0;
    for (var i in tourMarkerLayer) {
        var layer = tourMarkerLayer[i];
        var markers = [];
        for (var j in layer["places"]) {
            var mNumber = count++;
            var place = layer["places"][j];
            var icon = getIcon(place["icon"]);
            var title = place["name"];
            var iposn = new GLatLng(place["iposn"][0], place["iposn"][1]);
            var desc = place["desc"];
            var marker = createMarker(iposn, title, icon, mNumber, desc);
 
            markers.push(marker);
            allmarkers.push(marker);
        }
        mgr.addMarkers(markers, layer["zoom"][0], layer["zoom"][1]);
    }
    mgr.refresh();
}
 
// Methods used for the marker manager and setting it up cont.
function createMarker(iposn, title, icon, mNumber, desc) {
    var marker = new GMarker(iposn, { title: desc, icon: icon, draggable: false });
	GEvent.addListener(marker, "click", function() {
        loadXMLDoc(title);     // Call the AJAX function to get the tour data
    });
 
//    GEvent.addListener(marker, "mouseover", function() {
//    marker.openInfoWindowHtml(html); 
//		alert("You clicked the map.");
//    });
    return marker;
}
 
 
 
 
 
 
/////////////////////////
//  REGIONS FUNCTIONS //
///////////////////////
 
 
// Function to populate the region data required for the polygon overlays
function populateRegions() {
    var region;
    var hex_color;
    for (var i = 0; i < regions.length; i++) {
        region = regions[i];
        var polygon = regionPolys[i];
 
        var iconName = region["name"];
        var incolour = region["innercolour"];
        var outcolour = region["outercolour"];
        var points = region["points"];
        var panPos = region["panPos"];
        var zoomLevel = region["zoomLevel"];
 
        var region_bounds = new GLatLngBounds();
        var pts = [];
        for (var j = 0; j < points.length; j++) {
            lat_lng = new GLatLng(points[j][0], points[j][1]);
            pts[pts.length] = lat_lng;
            region_bounds.extend(lat_lng);
        }
 
        var opList = new Array();
        opList.push(createOperation("pan", panPos));
        opList.push(createOperation("zoomin", zoomLevel));
        regionClickData[i] = opList;
 
        polygon = createPolygon(pts, name, incolour, outcolour, i);
        map.addOverlay(polygon);
        regionPolys[i] = polygon;
        regionVisible[i] = true;
    }
}
 
// Methods used for creating the region polygons and providing the click function.
function createPolygon(pts, name, incolour, outcolour, number) {
    var  polygon = new GPolygon(pts, outcolour, 1, strokeOpacity, incolour, polyOpacity);
    //    polygon.tooltip = '<div class="tooltip">' + name + '<\/div>';
    GEvent.addListener(polygon, "mouseout", function() {
        document.getElementById("map_canvas").style.cursor = "default";
    });
    GEvent.addListener(polygon, "mouseover", function() {
        document.getElementById("map_canvas").style.cursor = "pointer";
    });
    GEvent.addListener(polygon, "click", function() {
        index = 0;
        opListCurrent = regionClickData[number];
        handleZoomEnd();
    });
    return polygon;
}
 
 
// Zoom functions
function createOperation(type, data) {
    var newObject = new Object();
 
    newObject.type = type;
    newObject.data = data;
 
    return newObject;
}
 
// Zoom functions cont.
function populateListToUpper() {
    opListToUpper = new Array();
    opListToUpper.push(createOperation("pan", NILocation));
    opListToUpper.push(createOperation("zoomin", NIZoomLevel));
}
 
 
// Zoom functions cont.
function populateListToLower() {
    opListToLower = new Array();
    opListToLower.push(createOperation("pan", SILocation));
    opListToLower.push(createOperation("zoomin", SIZoomLevel));
}
 
 
// Zoom functions cont.
function ZoomToUpper() {
//GLog.write("ZoomToUpper()");
    index = 0;
    opListCurrent = opListToUpper;
    handleZoomEnd();
}
 
 
// Zoom functions cont.
function ZoomToLower() {
//GLog.write("ZoomToLower()");
    index = 0;
    opListCurrent = opListToLower;
    handleZoomEnd();
}
 
// Function to reset the zoom level of the map if it is zoomed in.
function resetZoom() {
    opList = new Array();
    opList.push(createOperation("pan", normalLocation));
    if (map.getZoom() > normalZoomLevel)
        opList.push(createOperation("zoomout", ( normalZoomLevel )));
    else if (map.getZoom() < normalZoomLevel)
        opList.push(createOperation("zoomin", (normalZoomLevel)));
    index = 0;
    opListCurrent = opList;
    handleZoomEnd();
 
	populateRegions();
	populateListToUpper();
	populateListToLower();
 
}
 
// Code for chaining pan/zoom events by Tom Horn
var panTimeout = -1;
var zoomInTimeout = -1;
var zoomOutTimeout = -1;
 
function handlePan(i) {
    if (i == 0 && map.getZoom() == normalZoomLevel) {       // If we are on default level about to zoom
        for (var j = 0; j < regionPolys.length; j++) {      // Then remove the polygon overlays
            if (regionVisible[j] == true) {                 // before we zoom in.
                map.removeOverlay(regionPolys[j]);
                regionVisible[j] = false;
            }
        }
    }
    map.panTo(opListCurrent[i].data);
    if (i == 1 && map.getZoom() == normalZoomLevel) {       // If we are on default level after a zoom
        for (var k = 0; k < regionPolys.length; k++) {      // Then add polygon overlays once
            if (regionVisible[k] == false) {                // the map has finished panning.
                map.addOverlay(regionPolys[k]);
                regionVisible[k] = true;
            }
        }
    }
    panTimeout = -1;
    setTimeout("handleMoveEnd()", 1);               // incase we don't get the event
}
 
function handleZoomOut(i) {
//GLog.write("handleZoomOut("+i+") zoom="+map.getZoom());
 if (opListCurrent[index] && opListCurrent[index].type && opListCurrent[index].type == "zoomout" && opListCurrent[index].data != map.getZoom()) {
    map.zoomOut(map.getCenter(), true, true);
}
    zoomOutTimeout = -1;
    setTimeout("handleZoomEnd()", 1);               // incase we don't get the event
}
 
function handleZoomIn(i) {
//GLog.write("handleZoomIn("+i+") zoom="+map.getZoom());
 if (opListCurrent[index] && opListCurrent[index].type && opListCurrent[index].type == "zoomin" && opListCurrent[index].data != map.getZoom()) {
    map.zoomIn(map.getCenter(), true, true);
}
    zoomInTimeout = -1;
    setTimeout("handleZoomEnd()", 1);               // incase we don't get the event
}
 
function removePolygons() {
    for (var i = 0; i < regionPolys.length; i++)    // Remove the polygon overlays
        if (regionVisible[i] == true) {             // before we zoom in.
        map.removeOverlay(regionPolys[i]);
        regionVisible[i] = false;
    }
}
 
function addPolygons() {
    for (var i = 0; i < regionPolys.length; i++)    // Add polygon overlays once
        if (regionVisible[i] == false) {            // the map has zoomed out.
        map.addOverlay(regionPols[i]);
        regionVisible[i] = true;
    }
}
 
function handleOp() {
    if (opListCurrent == null || index < 0 || index >= opListCurrent.length) {
        index = -1;
        return;
    }
    var distance = 0;
    try
    {
        distance = map.getCenter().distanceFrom(opListCurrent[index].data);
    }
    catch(err){} // This failure will be down to the map already being in a movement, in this case ignore it.
 
    
    switch (opListCurrent[index].type) {
        case "zoomout":
//GLog.write("handleOp:zoomout index="+index+" zoom="+map.getZoom()+" opListCurrent[index].data="+opListCurrent[index].data);
            if (map.getZoom() > opListCurrent[index].data) {
                if (zoomOutTimeout == -1) { // no callbacks in flight
                    zoomOutTimeout = setTimeout("handleZoomOut (" + index + ")", operationTimeout);
//GLog.write("handleOp:zoomout zoomOutTimeout != -1, scheduled zoomout");
                }
                return;
            }
            break;
        case "zoomin":
//GLog.write("handleOp:zoomin index="+index+" zoom="+map.getZoom()+" opListCurrent[index].data="+opListCurrent[index].data);
            if (map.getZoom() < opListCurrent[index].data) {
                if (zoomInTimeout == -1) { // no callbacks in flight
                    zoomInTimeout = setTimeout("handleZoomIn (" + index + ")", operationTimeout);
//GLog.write("handleOp:zoomin zoomInTimeout != -1, scheduled zoomin");
                }
                return;
            }
            break;
        case "pan":
            if (distance > 3000) {
                if (panTimeout == -1) // no callbacks in flight
                    panTimeout = setTimeout("handlePan (" + index + ")", operationTimeout);
                return;
            }
            break;
        default:
            break;
    }
 
    index = index + 1;
}
 
function handleZoomEnd() {
    if (index >= 0)
        handleOp();
}
 
function handleMoveEnd() {
    if (index >= 0)
        handleOp();
}
