﻿/* 
* 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
var operationTimeout = 300; 	// Time in msec between each pan / scroll operation. Lower = faster

// Variables for marker data, leave as is.
var mgr;
var icons = {};
var allmarkers = [];

// Variables for operation chaining, leave as is.
var opListCurrent = null;
var opLists = [];
var index = -1;

// Variables for the zoom level and pan location for the Upper / Mid / Lower links.
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.402307, 168.810425);
var lowerZoomLevel = 7;

// Variables for the normal south island position and zoom level.
var normalLocation = new GLatLng(-43.53262, 170.99121);
var normalZoomLevel = 6;

// 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 }
};

// Region variables
var REGION_MAX_ZOOMLEVEL = 6;           // 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.1;
var strokeOpacity = 0;
var regionPolys = [];
var regions = [
{
    "name": "Upper South Island",
//  "innercolour": "red",
//  "outercolour": "#89C0FF",
    "panPos": upperLocation,
    "zoomLevel": upperZoomLevel,
    //    "points": [[-40.513799, 172.79296], [-40.830436, 172.814941], [-40.813809, 172.990722], [-41.162113, 173.12255859375], [-41.062786, 173.649902], [-40.747256, 173.825683], [-41.095912, 174.418945], [-41.442726, 174.089355], [-41.705728, 174.287109], [-42.569264, 173.518066], [-41.787697, 171.474609], [-41.442726, 171.979980], [-40.880294, 172.067871], [-40.513799, 172.79296]]
    "points": [[-39.419220, 163.630372], [-39.419220, 178.330078], [-42.30, 178.330078], [-42.30, 163.630372], [-39.419220, 163.630372]]
},
{
    "name": "Middle South Island",
 // "innercolour": "red",
 // "outercolour": "#7BFF47",
    "panPos": midLocation,
    "zoomLevel": midZoomLevel,
    "points": [[-42.30, 163.630372], [-42.30, 178.330078], [-44.97, 178.330078], [-44.97, 163.630372], [-42.30, 163.630372]]
},
{
    "name": "Lower South Island",
 //  "innercolour": "red",
 //  "outercolour": "#5972FF",
    "panPos": lowerLocation,
    "zoomLevel": lowerZoomLevel,
    "points": [[-44.97, 163.610372], [-44.97, 178.330078], [-47.368594, 178.330078], [-47.353710, 163.630372], [-44.353710, 163.630372]]
}
];

// 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": [6, 17],
    "places": [

     {
          "name": "Kaikoura",
          "icon": ["info", "info-shadow"],
          "iposn": [-42.37, 173.67],
          "desc": "Spend your day getting close to nature. Travel by road or train through the rolling hill country of North Canterbury, enjoying the beauty of its rural pastoral scenes, to 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": ["info", "info-shadow"],
          "iposn": [-43.53, 172.61],
          "desc": "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": "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"
      },
*/
    ]
}
];

// Initialize function to set up the Google map.
function initialize() {
    if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map_canvas"), { size: new GSize(670,500) });
        map.setMapType(G_NORMAL_MAP);
        map.disableDragging();
        map.disableDoubleClickZoom();
        map.enableContinuousZoom();
        map.setCenter(new GLatLng(-43.53262, 170.99121), 6);
        populateRegions();
        populateListToUpper();
        populateListToMid();
        populateListToLower();

        window.setTimeout(setupTourLocations, 0);

        GEvent.addListener(map, "zoomend", handleZoomEnd);
        GEvent.addListener(map, "moveend", handleMoveEnd);
    }
}

// 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;
}

// 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.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
    });
    return marker;
}

// 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", upperLocation));
    opListToUpper.push(createOperation("zoomin", upperZoomLevel));
}

// Zoom functions cont.
function populateListToMid() {
    opListToMid = new Array();
    opListToMid.push(createOperation("pan", midLocation));
    opListToMid.push(createOperation("zoomin", midZoomLevel));
}

// Zoom functions cont.
function populateListToLower() {
    opListToLower = new Array();
    opListToLower.push(createOperation("pan", lowerLocation));
    opListToLower.push(createOperation("zoomin", lowerZoomLevel));
}

// Zoom functions cont.
function ZoomToUpper() {
    index = 0;
    opListCurrent = opListToUpper;
    handleZoomEnd();
}

// Zoom functions cont.
function ZoomToMid() {
    index = 0;
    opListCurrent = opListToMid;
    handleZoomEnd();
}

// Zoom functions cont.
function 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 + 1 )));
    else if (map.getZoom() < normalZoomLevel)
        opList.push(createOperation("zoomin", (normalZoomLevel + 1)));
    index = 0;
    opListCurrent = opList;
    handleZoomEnd();
}

// 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) {
    map.zoomOut(map.getCenter(), true, true);
    zoomOutTimeout = -1;
    setTimeout("handleZoomEnd()", 1);               // incase we don't get the event
}

function handleZoomIn(i) {
    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(regionPolys[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":
            if (map.getZoom() > opListCurrent[index].data) {
                if (zoomOutTimeout == -1) // no callbacks in flight
                    zoomOutTimeout = setTimeout("handleZoomOut (" + index + ")", operationTimeout);
                return;
            }
            break;
        case "zoomin":
            if (map.getZoom() < opListCurrent[index].data) {
                if (zoomInTimeout == -1) // no callbacks in flight
                    zoomInTimeout = setTimeout("handleZoomIn (" + index + ")", operationTimeout);
                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();
}