var key = "ABQIAAAADB66ewLVwl_io_iD_gDbnBSyINyZ-Ki333KzDxtLhvY3RQOAHxTY3ekn19hxgyUA9SQ92mhYm0KimQ";

google.load("maps", "3",  {other_params:"sensor=false&amp;key="+key});
google.load("jquery", "1.3.2");

var map;
var locations = {ids: []};
// var data_url must be globally declared

var initial_zoom_level = 12;
var initial_lat = 60.02;
var initial_lng = 13.67;

// http://maps.google.com/maps?f=q&source=s_q&hl=sv&geocode=&q=hagfors,+sverige&sll=45.842075,-92.969227&sspn=0.079883,0.152435&g=hagfors,+sverige&ie=UTF8&hq=&hnear=Hagfors,+V%C3%A4rmlands+L%C3%A4n,+Sverige&ll=60.023804,13.672485&spn=0.014323,0.038109&z=15&iwloc=A

var pan_margin_lat = 40;
var pan_margin_lng = 120;

var update_interval = 2000;

function centerMap()
{
    if(locations.ids.length == 0)
        return;

    if(locations.ids.length == 1) {
        var center = locations[locations.ids[0]].latlng;
        map.setCenter(center);
    //    map.setZoom(12);
        return;
    }

    var bounds = new google.maps.LatLngBounds();
    for(var i=0; i<locations.length; i++)
        bounds.extend(locations[locations.ids[i]].latlng);
    map.fitBounds(bounds);
//    if(map.getZoom() > 12)
//        map.setZoom(12);
//}
}

function panMap()
{
    if(locations.ids.length == 0)
        return;

    if(locations.ids.length == 1) {
        var bounds = new google.maps.LatLngBounds();
        var center = locations[locations.ids[0]].latlng;
        var zoom_fac = Math.pow(2, map.getZoom());
        bounds.extend(new google.maps.LatLng(center.lat() - pan_margin_lat / zoom_fac, center.lng() - pan_margin_lng / zoom_fac));
        bounds.extend(new google.maps.LatLng(center.lat() + pan_margin_lat / zoom_fac, center.lng() + pan_margin_lng / zoom_fac));
        map.panToBounds(bounds);
        return;
    }

    var bounds = new google.maps.LatLngBounds();
    for(var i=0; i<locations.length; i++)
        bounds.extend(locations[locations.ids[i]].latlng);
    map.fitBounds(bounds);
}

function courseToCompass(course)
{
    var compass = [
        "N", "NNÖ", "NÖ", "ÖNÖ",
        "Ö", "ÖSÖ", "SÖ", "SSÖ",
        "S", "SSV", "SV", "VSV",
        "V", "VNV", "NV", "NNV"];
    var d = Math.round(course / (360.0/16.0));
    return compass[d % 16];
}

function infoWindowContent(loc, address)
{
    var contents = "<strong>" + loc.name + "</strong>";

    if(loc.speed != null && loc.course != null) {
        contents += "<br/>";
        if(loc.speed < 2.0) {
            contents += "(stillastående)";
        } else
            contents += Math.round(loc.speed) + " km/h, " + courseToCompass(loc.course);
    }

    return contents;
}

function updateInfoWindow(win, loc)
{
    /* This runs in the background */
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({'latLng': loc.latlng}, function(results, status) {
        if(status != google.maps.GeocoderStatus.OK)
            return;
        win.setContent(infoWindowContent(loc, results[0].formatted_address));
    });
}

function createInfoWindow(loc)
{
    var win = new google.maps.InfoWindow({content: infoWindowContent(loc, "&nbsp;")});
    updateInfoWindow(win, loc);

    return win;
}

function createLocation(id, elem)
{
    var loc = { id: id }
    updateLocation(loc, elem);
    loc.marker = new google.maps.Marker({position: loc.latlng, map: map});
    google.maps.event.addListener(loc.marker, "click", function() {
        if (loc.infowindow) loc.infowindow.close();
        loc.infowindow = createInfoWindow(loc);
        loc.infowindow.open(map, loc.marker);
    });
    return loc;
}

function updateLocation(loc, elem)
{
    var old_time = loc.time;

    loc.name = elem.attr("name");
    loc.latlng = new google.maps.LatLng(parseFloat(elem.attr("lat")), parseFloat(elem.attr("lng")));
    loc.time = elem.attr("time");
    loc.course = elem.attr("course");
    loc.course = loc.course == "" ? null : parseFloat(loc.course);
    loc.speed = elem.attr("spd");
    loc.speed = loc.speed == "" ? null : parseFloat(loc.speed);
    loc.altitude = elem.attr("alt");
    loc.altitude = loc.altitude == "" ? null : parseFloat(loc.altitude);

    if(loc.time != old_time) {
        if(loc.marker)
            loc.marker.setPosition(loc.latlng);
        if (loc.infowindow) {
            loc.infowindow.setPosition(loc.latlng);
            updateInfoWindow(loc.infowindow, loc);
        }
    }
}

function updateLocations()
{
    jQuery.get(data_url + "?" + Math.random() * 10000, {}, function(data) {
        if (typeof data == "string" && $.browser.msie) {
            var xml = new ActiveXObject("Microsoft.XMLDOM");
            xml.async = false;
            xml.loadXML(data);
            data = xml;
        }
        jQuery(data).find("marker").each(function() {
            var marker_elem = jQuery(this);
            var id = marker_elem.attr("id");
            /* TODO: delete removed locations */
            updateLocation(locations[id], marker_elem);
        });
        panMap();
        window.setTimeout(function() { updateLocations(); }, update_interval);
    });
}

function initialize() {
    var canvas = document.getElementById("map_canvas");

    function resize()
    {
        //canvas.style.width = "" + window.innerWidth + "px";
        //canvas.style.height = "" + window.innerHeight + "px";

        /* Use jQuery for cross-browser compability */
        canvas.style.width  = "" + $(window).width() + "px";
        canvas.style.height = "" + $(window).height() + "px";
    }
    resize();

    window.onresize=resize;

    var myOptions = {
        zoom: initial_zoom_level,
        center: new google.maps.LatLng(initial_lat, initial_lng),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    map = new google.maps.Map(canvas, myOptions);

    // For more information on doing XMLHR with jQuery, see these resources:
    // http://net.tutsplus.com/tutorials/javascript-ajax/use-jquery-to-retrieve-data-from-an-xml-file/
    // http://marcgrabanski.com/article/jquery-makes-parsing-xml-easy
    jQuery.get(data_url + "?" + Math.random() * 10000, {}, function(data) {
        if (typeof data == "string" && $.browser.msie) {
            var xml = new ActiveXObject("Microsoft.XMLDOM");
            xml.async = false;
            xml.loadXML(data);
            data = xml;
        }

        locations.length = 0;
        jQuery(data).find("marker").each(function() {
            var marker_elem = jQuery(this);
            var id = marker_elem.attr("id");
            locations.ids.push(id);
            locations[id] = createLocation(id, marker_elem);
        });
        centerMap();
    });

    window.setTimeout(function() { updateLocations(); }, update_interval);
}

google.setOnLoadCallback(initialize);

