﻿/* requires jquery-1.4.1.min.js ---------------------------------*/
/* ------------------------------------------------------------- */
/* ------------------------------------------------------------- */


jQuery().ready(function() {


   
    /* ---- USER REGISTRATION CONTROL ----------------------------------------------------------------- */
    // Handles diaplay / hide of user registration / account panels and buttons.
    // For anonymous users, all panels with the accordionContent class are hidden.
    // For autheticated users, all input field panels are displayed to allow update of information.
    if ($("input[id$='hdnUserType']").val() == "ANONYMOUS") {
        $(".accordionContent").hide();
        $("input[id$='btnNextRegistrationStage1']").toggle();
    }
    // For B2B users: make all input controls read-only
    else if ($("input[id$='hdnUserType']").val() == "B2B") {
        $('input:not(.btn), select').attr('disabled', 'disabled');
    }

    if ($("div[id$='GM_map_canvas']").attr("id") != null) {

        // Class Definition - holds all marker information
        function PointInformation(point, dist) {
            this.Point = point;
            this.Distance = dist;
            this.PrimaryInfoData = "";
            this.HtmlInfo = null;
            this.setDistance = function(pointFrom) {
                var rawDistance = this.Point.distanceFrom(pointFrom.Point);
                this.Distance = convertRawDistance(rawDistance);
            };
        }

        var pointArray = new Array();
        var markers = [];
        var currentMarkerIndex = 0;

        var localSearch = new GlocalSearch();

        // Initialise .NET properties //

        // If set to true - displays side panel consisting of all added map markers
        var displayIndexPanel = $("input[id$='hdnGMDisplayIndexPanel']").val() == "True";

        // Specifies initial zoom level of map - if set to 0, zoom level is automatically set.
        var zoomLevel = parseInt($("input[id$='hdnGMZoomLevel']").val());

        // Specifies postcode to center on and helps to set zoom level.
        var postcode = $("input[id$='hdnPostcode']").val();

        // Specifies whether distabnce is in KMs or miles
        var distanceIn = $("input[id$='hdnDistanceUnits']").val();  // miles or km

        // Specifies how many nearest markers to display from the postcode given
        var nearestNeighbours = parseInt($("input[id$='hdnNearestNeighbours']").val()); ;

        // Specifies the set of XML nodes for the marker information
        var xmlMarkerNodes = $("input[id$='hdnXMLMarkerNodes']").val();

        // Specifies whether to display distance information
        var displayDistance = $("input[id$='hdnDisplayDistance']").val();

        // Specifies the format template of the html marker inforamtion
        var markerInfoTemplate = $("input[id$='hdnMarkerInfoTemplate']").val();

        // Specifies whether to display the marker information
        var displayMarkers = $("input[id$='hdnShowMarkers']").val() == "True";

        // Specifies the xmlPath and name
        var xmlFileWithPath = $("input[id$='hdnGMXMLPath']").val();
        if (xmlFileWithPath.length = 0) {
            displayMarkers = false;
        }

        function initialize() {

            // Get the map canvas DOM object
            var mapRegion = document.getElementById("GM_map_canvas");

            // Creates an object of type GMap2
            var map = new GMap2(mapRegion);

            // Displays the default Google Map UI controls
            map.setUIToDefault();

            if (postcode.length > 0) {
                // Get the lat/lng for the set postcode
                LatLngFromPostcode(postcode, function(resultLat, resultLng) {

                    var pointInfo = null;
                    if (resultLat.length > 0 && resultLng.length > 0) {
                        // On callback, create the reference point from which all other marker distances are calculated from.
                        var referencePoint = new GLatLng(resultLat, resultLng);
                        pointInfo = new PointInformation(referencePoint, 0);

                        // TRY TO ADD WHERE WE ARE MARKER!!!!!
                        var weAreHere = new GIcon(G_DEFAULT_ICON);
                        weAreHere.image = "/content/shared/images/icon_google_youarehere.png";
                        var markerOptions = { icon: weAreHere };
                        map.addOverlay(new GMarker(pointInfo.Point, markerOptions));
                    }

                    if (displayMarkers) {
                        // Process xml file - pass reference point previously created
                        ProcessXMLFile(map, pointInfo);
                    }
                    else {
                        // Center map and set zoom level
                        FinalizeMap(map, pointArray, pointInfo);
                    }
                });
            }
            else {
                if (displayMarkers) {
                    // process xml file = pass null as reference point as no postcode was set
                    ProcessXMLFile(map, null);
                }
            }

            $("#message").appendTo(map.getPane(G_MAP_FLOAT_SHADOW_PANE));

        }
        google.setOnLoadCallback(initialize);
    }

    // Function: Parses the xml file containing all marker information and processes each marker block in turn
    function ProcessXMLFile(map, postcodeReferencePoint) {

        // Downloads all data in googleLocations.xml and loads it onto the map.
        // Then calls function FinalizeMap which creates all the markers, sets initial zoom level, and centers map
        GDownloadUrl(xmlFileWithPath, function(data) {
            xml = GXml.parse(data);
            markers = xml.documentElement.getElementsByTagName("Marker");
            ProcessNextMarker(map, postcodeReferencePoint);

        });
    }

    function ProcessNextMarker(map, postcodeReferencePoint) {

        // NEEDS ADDRESSING - limit amount of xml markers to 40!! Just takes way too long to process to have any more!!!!!
        if ((currentMarkerIndex < markers.length) && currentMarkerIndex < 40) {
            ProcessXMLMarker(map, postcodeReferencePoint, markers[currentMarkerIndex++]);
        }
        else {
            // Center map and set zoom level
            FinalizeMap(map, pointArray, postcodeReferencePoint);
        }
    }

    // Function : Creates each marker in pointArray, calculates the boundary of map based on pointArray 
    // and sets the initial zoom level and center of map
    function FinalizeMap(map, pointArray, postcodeReferencePoint) {

        if (displayMarkers) {
            for (var i = 0; i < pointArray.length; i++) {
                CreateMarker(map, pointArray[i]);
            }
            var maxMarkers = pointArray.length;
        }

        if (postcodeReferencePoint != null) {
            pointArray.push(postcodeReferencePoint);
        }

        // if we have a postcode - limit the number of markers we display by the .NET property value (nearestNeighbours)
        nearestNeighbours = 1;
        if (postcodeReferencePoint != null) {
            if (nearestNeighbours > 0) {
                // If we are displaying the marker information - limit the number to value specified + 1 (referencepoint), otherwise only display the reference point marker (we are here!)
                if (displayMarkers) {
                    maxMarkers = nearestNeighbours + 1;
                }
                else {
                    maxMarkers = 1;
                }
            }
            else {
                maxMarkers = 1;
            }
        }

        // Extends the map boundary
        var bounds = new GLatLngBounds();
        for (var i = 0; i < maxMarkers; i++) {
            if (pointArray[i] != undefined) {
                bounds.extend(pointArray[i].Point);
            }
        }
        map.setCenter(bounds.getCenter());

        // Set zoom level
        if (zoomLevel != 0) {
            map.setZoom(zoomLevel);
        }
        else {
            map.setZoom(map.getBoundsZoomLevel(bounds));
        }
    }

    // Function: converts google map raw distance data to either kms or miles
    function convertRawDistance(dist) {

        var convertedDist = dist / 1000; // converts to KM
        if (distanceIn.toLowerCase() == "miles") {
            convertedDist = convertedDist * 0.621371192;
        }
        return convertedDist.toFixed(2);
    }

    // Function: 
    function createPoint(latitude, longitude, postCodeReferencePoint) {

        // Creates a Google GLatLng object 
        var point = new GLatLng(latitude, longitude);

        var orderedPoint = new PointInformation(point, 0);
        if (postCodeReferencePoint != null) {
            // If or point of reference is set - calculate the distance from it for this point
            orderedPoint.setDistance(postCodeReferencePoint);

            // Place the point in order of - nearest to set postcode 
            var bPointAdded = false;
            for (var x = 0; x < pointArray.length; x++) {
                if (parseFloat(orderedPoint.Distance) < parseFloat(pointArray[x].Distance)) {
                    pointArray.splice(x, 0, orderedPoint);
                    bPointAdded = true;
                    break;
                }
            }

            // if the point was not previously added, add it at the end
            if (!bPointAdded) {
                pointArray.push(orderedPoint);
            }
        }
        else {
            pointArray.push(orderedPoint);
        }

        return orderedPoint;
    }

    // Function : Creates a marker given a PointInformation object
    function CreateMarker(map, pointInfo) {

        var marker = new GMarker(pointInfo.Point);

        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(pointInfo.HtmlInfo);
        });

        if (displayIndexPanel) {
            var htmlInfo = pointInfo.PrimaryInfo;
            if (pointInfo.Distance > 0 && displayDistance) {
                htmlInfo += "<BR/>Distance: " + pointInfo.Distance + " " + distanceIn;
            }
            if (htmlInfo != undefined) {
                $("<li />").html(htmlInfo).click(function() {
                    marker.openInfoWindowHtml(pointInfo.HtmlInfo);
                })
                .appendTo("#list");
            }
        }

        // Add the marker to map
        map.addOverlay(marker);

        return marker;
    }

    // Function : Creates a marker (consisting of point and additional data) from the XMLMArker
    function ProcessXMLMarker(map, postcodeReferencePoint, xmlMarker) {

        var markerInfo = new Object;

        var lat = "";
        var longitude = "";

        // Retrieve the latitude information from XMLMarker
        if (xmlMarker.getElementsByTagName("Latitude")[0] != undefined && xmlMarker.getElementsByTagName("Latitude")[0].firstChild != undefined) {
            lat = xmlMarker.getElementsByTagName("Latitude")[0].firstChild.nodeValue;
        }

        // Retrieve the longitude information from XMLMarker
        if (xmlMarker.getElementsByTagName("Longitude")[0] != undefined && xmlMarker.getElementsByTagName("Longitude")[0].firstChild != undefined) {
            longitude = xmlMarker.getElementsByTagName("Longitude")[0].firstChild.nodeValue;
        }

        if (lat.length == 0 || longitude.length == 0) {

            // Lat/Lng data not present - search for a postcode node...
            if (xmlMarker.getElementsByTagName("PostCode")[0] != undefined && xmlMarker.getElementsByTagName("PostCode")[0].firstChild != undefined) {
                var postcode = xmlMarker.getElementsByTagName("PostCode")[0].firstChild.nodeValue;
                if (postcode.length > 0) {
                    // Get Lat/Lng from postcode
                    LatLngFromPostcode(postcode, function(resultLat, resultLng) {
                        // Only create the point if valid data has been returned
                        if (resultLat.length > 0 && resultLng.length > 0) {

                            // Create the point and build marker information
                            var point = createPoint(resultLat, resultLng, postcodeReferencePoint);
                            BuildMarkerInfo(xmlMarker, markerInfo, point);
                        }
                        ProcessNextMarker(map, postcodeReferencePoint);
                    });
                }
            }
            else {
                // Could not find lat/lng or postcode nodes - Skipping this marker.
                ProcessNextMarker(map, postcodeReferencePoint);
            }
        }
        else {
            // Create the point and build marker information
            var point = createPoint(lat, longitude, postcodeReferencePoint);
            BuildMarkerInfo(xmlMarker, markerInfo, point);
            ProcessNextMarker(map, postcodeReferencePoint);
        }
    }

    // Function: Builds the html additional information for the xmlMarker
    function BuildMarkerInfo(xmlMarker, markerInfo, point) {

        var infoArgs = [];

        var html = markerInfoTemplate;

        // Get the value of each XMLMarker Node and store in array
        var xmlMakerInfo = xmlMarkerNodes.split(",");
        for (var x = 0; x < xmlMakerInfo.length; x++) {

            if (xmlMarker.getElementsByTagName(xmlMakerInfo[x])[0] != undefined && xmlMarker.getElementsByTagName(xmlMakerInfo[x])[0].firstChild != undefined) {
                infoArgs[x] = xmlMarker.getElementsByTagName(xmlMakerInfo[x])[0].firstChild.nodeValue;

                // Assumes primary is always first node.
                if (x == 0) point.PrimaryInfo = infoArgs[x];
            }
        }

        // subtitude placeholders of (markerInfoTemplate) with node values
        var html = strsubstno(markerInfoTemplate, '\\{', infoArgs, '\\}');

        markerInfo.value = html;
        if (point.Distance > 0 && displayDistance) {
            markerInfo.value += "<br/>Distance (" + distanceIn + ") : " + point.Distance;
        }

        // Store the marker information for later use against the point
        point.HtmlInfo = markerInfo.value;
        return point.HtmlInfo;
    }

    // Function: Takes a UK postcode and returns Lat/Lng data
    function LatLngFromPostcode(postcode, callBackFunction) {

        localSearch.setSearchCompleteCallback(null,
            function() {
                if (localSearch.results[0]) {
                    var resultLat = localSearch.results[0].lat;
                    var resultLng = localSearch.results[0].lng;
                    callBackFunction(resultLat, resultLng);

                } else {
                    // skip this marker - ERROR
                    callBackFunction("", "");
                }
            });
        localSearch.execute(postcode + ", UK");
    }

});



