﻿// Default.htm.js : v0.9 02/02/2009
// Copyright 2009 Hugh Saalmans : hugh@minus34.com
//
// Feel free to use the code...
// ...but please acknowledge someone else's efforts! :-)
//

var map = null;
var l = 4;
var geomUrl = "../m34Cmn/GetDataAndStats.ashx";
var statUrl = "../m34Cmn/GetStats.ashx";
var overShpId = null;
var currCids = [];
var currMultiShapeIds = [];
//var themeValues = [];
var currRequests = 0;
var userGoneCrazy = false;
var timerID = 0;
var dX = 55;
var dY = 130;
var w = 99999;
var h = 99999;
var polySL = null;
var selLineColour = null;
var selLineWidth = 4;
var selZLevel = 60;
var currLineColor = null;
var currLineWidth = 2;
var currZLevel = 50;
var currGroup = "B02";
var currTheme = "B109";
var currThemeId = 0;
var currGroupArray = [];
var currGroupArrayLen = 0;
var statGroupChanged = false;

var B02 = [["Median Age", "B109"],
           ["Median Individual income", "B110"],
           ["Median Family income", "B111"],
           ["Median Household income", "B112"],
           ["Median Home loan repayment", "B113"],
           ["Median Rent", "B114"],
           ["Average people per bedroom", "B115"],
           ["Average household size", "B116"]];

var BXX = [["Item 1", "BXX1"], ["Item 2", "BXX2"], ["Item 3", "BXX3"], ["Item 4", "BXX4"]];



var el = document.createElement("div");
el.id = "info";
el.style.fontFamily = "Arial";
el.style.fontSize = "small";
el.style.fontWeight = "bold";
el.style.color = "#FFFFFF";
el.style.backgroundColor = "#0B56B2";
el.style.border = "2px solid #0000CC";
el.style.opacity = 0.9;
el.style.filter = "alpha(opacity=90)";
el.style.textAlign = "center";
el.style.verticalAlign = "middle";
el.style.position = "absolute";

var el2 = document.createElement("div");
el2.id = "info2";
el2.style.fontFamily = "Arial";
el2.style.fontSize = "large";
//el2.style.fontWeight = "bold";
el2.style.color = "#002000";
el2.style.backgroundColor = "#AACCAA";
el2.style.border = "3px solid #99DD99";
el2.style.opacity = 0.8;
el2.style.filter = "alpha(opacity=80)";
el2.style.textAlign = "center";
el2.style.verticalAlign = "middle";
el2.style.position = "absolute";
el2.innerHTML = "&nbsp;L O A D I N G &nbsp; D A T A . . . &nbsp;"

//
//jQuery code below adapted from John O'Brien's (Soul Solutions) code
//http://soulsolutions.com.au/Blog/tabid/73/EntryId/528/Virtual-Earth-Basics-Part-1-Loading-the-Map.aspx
//

$(window).unload(function() {if (map) map.Dispose();});
$.getScript = function(url, callback, cache) {$.ajax({type: "GET",url: url,success: callback,dataType: "script",cache: cache});};

$(document).ready(function() {
    Resizer();
    if (!($.browser.msie) && !($.browser.mozilla) && !($.browser.safari)) {
        $("#myMap").html("Virtual Earth is not supported by your browser.<br/><br/>Try Internet Explorer, Firefox, Safari or Chrome...")
    } else {
    $("#myMap").addClass("maploading");
        $.getScript("js/Suburbs.js", "", true);
        $.getScript("js/getSubs.js", "", true);
        if (!($.browser.msie)) $.getScript("http://dev.virtualearth.net/mapcontrol/v6.2/js/atlascompat.js", "", true);
        $.getScript("http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&onScriptLoad=onscriptload", "", true);
    }
});

function onscriptload() {
    //
    //VE Multishape library from Richard Brundritt (Infusion Development)
    //http://rbrundritt.spaces.live.com/
    //
    $.getScript("js/Multishape.js", GetMap, true);
}

function GetMap() {
    $("#myMap").removeClass("maploading");
    map = new VEMap("myMap");
    //Can't use onLoadMap - AddControl fails claiming the map isn't loaded - known issue.
    //map.onLoadMap = onMapLoaded;
    //Can't get EnableBirdseye = false to work...
    //var veOptions = new VEMapOptions();
    //veOptions.EnableBirdseye = false;
    //map.LoadMap(new VELatLong(-30, 133), l, VEMapStyle.Hybrid, false, VEMapMode.Mode2D, true, 0, veOptions);
    map.LoadMap(new VELatLong(-30, 133), l, VEMapStyle.Hybrid, false, VEMapMode.Mode2D, true, 0);
    polySL = new VEShapeLayer();
    map.AddShapeLayer(polySL);
    //polySL.Hide();
    selLineColor = new VEColor(0, 255, 0, 0.5)
    MultiShape.prototype.censusId = "";
    MultiShape.prototype.stats = [];
    currGroupArray = window[currGroup];
    currGroupArrayLen = currGroupArray.length;
    //MultiShape.prototype.themeValue = 0.0;
    //map.vemapcontrol.SetAnimationEnabled(false);
    map.Hide3DNavigationControl();
    map.SetMouseWheelZoomToCenter(false);
    map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);
    map.EnableShapeDisplayThreshold(false);
    map.AttachEvent("onstartpan", function() { StopEvents(); });
//    map.AttachEvent("onstartzoom", function() { StopEvents(); map.DeleteAllShapeLayers(); currCids = []; currMultiShapeIds = []; map.ShowControl(el2); });
//    map.AttachEvent("onendpan", function() { map.DeleteAllShapeLayers(); currCids = []; currMultiShapeIds = []; map.ShowControl(el2); MapChange(); });
    map.AttachEvent("onstartzoom", function() { StopEvents(); polySL.DeleteAllShapes(); currCids = []; currMultiShapeIds = []; map.ShowControl(el2); });
    map.AttachEvent("onendpan", function() { polySL.DeleteAllShapes(); currCids = []; currMultiShapeIds = []; map.ShowControl(el2); MapChange(); });
    map.AttachEvent("onendzoom", function() { l = map.GetZoomLevel(); MapChange(); });
    map.AttachEvent("onmousemove", OnMouseEvent);
    map.AttachEvent("onmouseout", OnMouseEvent);
    map.AddControl(el);
    map.AddControl(el2);
    MapChange();
    //Show Suburb And Statistics selector
    document.getElementById("d").style.visibility = "visible";
    //document.getElementById("d2").style.visibility = "visible";
    document.getElementById("d3").style.visibility = "visible";
    //Use setInterval to overcome window.onresize being a  F A R C E  across the browser types...
    timerID = setInterval("Resizer()", 1000);
}

function Resizer() {
    var newW = 0;
    var newH = 0;

    if ($.browser.msie) {
        newW = document.documentElement.clientWidth;
        newH = document.documentElement.clientHeight;
    } else {
        newW = window.innerWidth;
        newH = window.innerHeight;
    }

    if (w != newW | h != newH) {
        w = newW;
        h = newH;
        ResizeMap();
    }
}

function ResizeMap() {
    var mapWidth = w - dX;
    var mapHeight = h - dY;

    var el2Left = mapWidth / 2 - 80;
    var el2Top = mapHeight / 2 + 100;
    el2.style.left = el2Left.toString() + "px";
    el2.style.top = el2Top.toString() + "px";

    if (map) {
        //Delete and Add as el2 doesn't move if you just hide and show.
        map.DeleteControl(el2);
        map.AddControl(el2);
        map.Resize(mapWidth, mapHeight);
    } else {
        $("#myMap").width(mapWidth);
        $("#myMap").height(mapHeight);
    }
}

function StopEvents() {
    map.DetachEvent("onmousemove", OnMouseEvent);
    map.DetachEvent("onmouseout", OnMouseEvent);
    map.HideControl(el);
}

function MapChange() {
    currRequests++;
    if (currRequests == 1) {
        var mapStyle = map.GetMapStyle();
        if (mapStyle == VEMapStyle.Aerial || mapStyle == VEMapStyle.Hybrid || mapStyle == VEMapStyle.Road || mapStyle == VEMapStyle.Shaded) getPolys();
    } else {
        currRequests--;
        userGoneCrazy = true;
    }
}

function getPolys() {
    var view = map.GetMapView();
    var br = view.BottomRightLatLong;
    var tl = view.TopLeftLatLong;
    var ua = [];
    ua.push(geomUrl);
    ua.push("?L=");
    ua.push(String(tl.Longitude));
    ua.push("&B=");
    ua.push(String(br.Latitude));
    ua.push("&R=");
    ua.push(String(br.Longitude));
    ua.push("&T=");
    ua.push(String(tl.Latitude));
    ua.push("&Z=");
    ua.push(l.toString());
    ua.push("&G=");
    ua.push(currGroup);
    ua.push("&V=");
    ua.push(currTheme);
    var reqStr = ua.join('');
    $.getScript(reqStr, "", true);
}

sh = function getS(js) {
    var geomStrArray = js[0];
    var censusID = js[1];
    var title = js[2];
    var statArray = js[3];
    var col = parseInt(js[4]);
    var col2 = 254 - col;

    var numGeoms = geomStrArray.length;
    currCids.push(censusID);

    var j = 0;
    var shapeArray = [];

    var multiSh = new MultiShape();
    //var multiShId = multiSh.id;

    for (var i = 0; i < numGeoms; i++) {
        var p = decodeLine(geomStrArray[j]);

        try {
            var veS = new VEShape(VEShapeType.Polygon, p);
            //veS.SetTitle(title);
            veS.SetZIndex(null, currZLevel);
            veS.SetLineWidth(2);
            shapeArray.push(veS);
        } catch (err) {
            alert("Add Shape failed!\n\n" + err.name + "\n\n" + err.message + "\n\n" + err.source);
        }
        j++
    }

    if (shapeArray.length > 0) {
        multiSh.shapes = shapeArray;
        multiSh.HideIcon();
        multiSh.SetTitle(title);
        multiSh.censusId = censusID;
        multiSh.stats = statArray;
        //multiSh.themeValue = themeVal;
        currMultiShapeIds.push(multiSh.id);
        return multiSh;
    } else return 1;
}

sl = function getSL(js) {
    var numPolys = js.length;
    var j = 0;
    for (var i = 0; i < numPolys; i++) {
        var newMultiShape = js[j];
        if (newMultiShape != 1) polySL.AddShape(newMultiShape);
        j++;
    }
    ChangeTheme()
    showPolys(polySL);
    return 1;
}

function noData() {
    currRequests--;
    map.AttachEvent("onmousemove", OnMouseEvent);
    map.AttachEvent("onmouseout", OnMouseEvent);
    map.HideControl(el2);
    //alert("Sorry - Australia only...");
    //alert("No New Data");
}

function dataError() {
    currRequests--;
    map.AttachEvent("onmousemove", OnMouseEvent);
    map.AttachEvent("onmouseout", OnMouseEvent);
    map.HideControl(el2);
    alert("Sorry - something bad happened... try it again!");
}


function showPolys(polySL) {
    currRequests--;
    //In case you're wondering - this is an attempt to limit calling for new data
    // when the user holds down the zoom in or out tool or generally zooms and pans like a crazy person...
    if (userGoneCrazy && currRequests == 1) {
        userGoneCrazy = false;
        //Call getPolys one more time as the data being returned is for previous map extents
        getPolys();
    } else {
        overShpId = null;
        //polySL.Show();
        //map.AddShapeLayer(polySL);
        map.AttachEvent("onmousemove", OnMouseEvent);
        map.AttachEvent("onmouseout", OnMouseEvent);
        map.HideControl(el2);
    }
}

function OnMouseEvent(e) {
    if (e.eventName == "onmousemove") {
        var shId = e.elementID;
        
        try {
            if (shId != null) {
                var shape = map.GetShapeByID(shId);
                //NOTE: VEShape.parentId not supported
                var id = shape.parentId;

                if (id != overShpId) {
                    if (overShpId) SetColour(overShpId, false);
                    overShpId = id;
                    SetColour(id, true)
                    el.innerHTML = GetStatsHTML(id);
                    SetMousePos(e);
                    map.ShowControl(el);
                } else {
                    SetMousePos(e);
                }
            } else {
                SetColour(overShpId, false);
                overShpId = null;
                map.HideControl(el);

            }
        } catch (err) {
            alert("mouseover event error!\n" + err.message);
            SetColour(overShpId, false);
            overShpId = null;
            map.HideControl(el);
        }
    } else if (e.eventName == "onmouseout") {
        SetColour(overShpId, false);
        overShpId = null;
        map.HideControl(el);
    }
}

function SetColour(id, highlight) {
    if (id != null) {
        var numShapes = polySL.GetShapeCount();
        var j = 0;
        for (var i = 0; i < numShapes; i++) {
            var bdy = polySL.GetShapeByIndex(j);
            if (bdy.parentId == id) {
                if (highlight) {
                    currLineColor = bdy.GetLineColor();
                    currLineWidth = bdy.GetLineWidth();

                    bdy.SetZIndex(null, selZLevel);
                    bdy.SetLineColor(selLineColor);
                    bdy.SetLineWidth(selLineWidth);
                } else {
                    bdy.SetZIndex(null, currZLevel);
                    bdy.SetLineColor(currLineColor);
                    bdy.SetLineWidth(currLineWidth);
                }

                //el.innerHTML = "&nbsp;" + bdy.GetTitle() + "&nbsp;";
            }
            j++
        }

    } else map.HideControl(el);
}

function GetStatsHTML(id) {
    var bdy = map.GetShapeByID(id);
    var statArray = bdy.stats;

    //Do this using an array - quicker than string concatentation (supposedly - haven't tested this one)
    var statsHTML = [];
    statsHTML.push("&nbsp;");
    statsHTML.push(bdy.GetTitle());
    statsHTML.push("&nbsp;");

    if (statArray) {
        statsHTML.push("<br/><br/>");

        if (currGroupArrayLen == statArray.length) {
            for (var i = 0; i < currGroupArrayLen; i++) {
                statsHTML.push("&nbsp;");
                statsHTML.push(currGroupArray[i][0]);
                statsHTML.push(" : ");
                statsHTML.push(statArray[i]);
                statsHTML.push("&nbsp;<br/>");
            }
            return statsHTML.join('');
        } else {
            StatsError();
            return "";
        }
    }
}

function SetMousePos(e) {
    var posx = 0;
    var posy = 0;
    if (e.pageX || e.pageY) {
        posx = e.pageX;
        posy = e.pageY;
    } else if (e.clientX || e.clientY) {
        posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    el.style.left = parseInt(posx + 10) + "px";
    el.style.top = parseInt(posy + 15) + "px";
}


function setStatType(sel) {
    //Get the user's selection
    currGroup = sel.value;
    currGroupArray = window[currGroup];
    currGroupArrayLen = currGroupArray.length;

    //Flag to control whether new stats are pulled from the server
    statGroupChanged = true;
    
    var statList = document.getElementById("cenSel2");
    for (var i = statList.length - 1; i >= 0; i--) { statList.remove(i); }

    if (currGroup != "dummy") {
        statList.options[statList.options.length] = new Option("Select ...", "dummy", false, true);

        var currStatType = eval(currGroup);
        var len = currStatType.length;

        for (var i = 0; i < len; i++) {
            statList.options[statList.options.length] = new Option(currStatType[i][0], currStatType[i][1], false, false);
        }
    }
}

function setMapTheme(sel) {
    currThemeId = sel.selectedIndex - 1;
    currTheme = sel.value;

    if (statGroupChanged) {
        statGroupChanged = false;
        GetTheStats();
    } else {
        //Change the map theme
        ChangeTheme();
    }
}

function GetTheStats() {
    var ua = [];
    ua.push(statUrl);
    ua.push("?G=");
    ua.push(currGroup);
    ua.push("&V=");
    ua.push(currTheme);
    ua.push("&Z=");
    ua.push(l.toString());
    ua.push("&I=");

    //Add boundary ID List
    //if (currCids != []) {
        ua.push("&IDS=");
        var ids = currCids.join();
        ua.push(ids);
    //}

    var reqStr = ua.join('');
    $.getScript(reqStr, "", true);
}

function StatsError() {
    map.HideControl(el2);
    alert("Sorry - something bad happened to the stats... try it again!");
}

//FAIL - doesn't work for Hashtables (have no idea why though)
//Array.prototype.getUniqueValues = function() {
//    var hash = new Object();
//    for (j = 0; j < numShpIds; j++) { hash[this[j]] = true }
//    var array = new Array();
//    for (value in hash) { array.push(value) };
//    return array;
//}


showStats = function getStats(js) {
    var j = 0;

    for (var i = 0; i < js.length; i++) {
        SetPolygonStats(js[j]);
        j++;
    }
    return 1;
}

function SetPolygonStats(js) {
    var cid = js[0];
    var col = js[1];
    //var stats = js[2];

    for (var iStr in shpIds) {
        if (shpIds[iStr] == cid) {
            var bdy = polySL.GetShapeByID(iStr);

            //Set the new colour
            var col2 = 255 - col;
            bdy.SetLineColor(new VEColor(col, 0, col2, 0.4));
            bdy.SetFillColor(new VEColor(col, 0, col2, 0.2));

            //Set the stats
            bdy.Stats = js[2];
        }
    }
}

function ChangeTheme() {
    var themeStats = [];
    //Get the min and max values for the theme statistic
    var min = 99999999;
    var max = -99999999;
    for (var i in currMultiShapeIds) {
        var bdy = polySL.GetShapeByID(currMultiShapeIds[i]);
        var stat = bdy.stats[currThemeId];
        themeStats.push(stat);

        if (stat != 0) if (stat < min) min = stat;

        if (stat > max) max = stat;
    }

    //Set the colour for each MultiShape
    SetThemeColour(themeStats, min, max);
}

function SetThemeColour(themeStats, min, max) {
    for (var i in currMultiShapeIds) {
        var id = currMultiShapeIds[i];
        var stat = themeStats[i];
        var col = 0;
        //Return mid colour if no range
        if (min == max) band = 0.5;
        //Set colour based on percentage between min and max
        else col = parseInt(254 * (stat - min) / (max - min));
        var col2 = 255 - col;
        //Step through each shape and change colour where shape is part of the current MultiShape
        var numShapes = polySL.GetShapeCount();
        var j = 0;
        for (var i = 0; i < numShapes; i++) {
            var bdy = polySL.GetShapeByIndex(j);
            if (bdy.parentId == id) {
                //show stats = 0 as white
                if (stat == 0) {
                    bdy.SetLineColor(new VEColor(128, 128, 128, 0.4));
                    bdy.SetFillColor(new VEColor(128, 128, 128, 0.2));
                } else {
                    bdy.SetLineColor(new VEColor(col, 0, col2, 0.4));
                    bdy.SetFillColor(new VEColor(col, 0, col2, 0.2));
                }
            }
            j++
        }
    }
}













//Code below courtesy of Google
function decodeLine(encoded) {
    var len = encoded.length;
    var index = 0;
    var array = [];
    var lat = 0;
    var lng = 0;
    var j = 0;
    while (index < len) {
        var b;
        var shift = 0;
        var result = 0;
        do {
            b = encoded.charCodeAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lat += dlat;
        shift = 0;
        result = 0;
        do {
            b = encoded.charCodeAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lng += dlng;
        array[j++] = new VELatLong(lat * 1e-5, lng * 1e-5);
    }
    return array;
}
