﻿Type.registerNamespace("Mcw.Rijksoverheid.GoogleMaps");

Mcw.Rijksoverheid.GoogleMaps.MapViewerControl = function (element) {
    Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.initializeBase(this, [element]);

    this._progressBar = null;
    this._timer = null;
    this._min = 0;
    this._max = 12;
    this._blXmlIsLoaded = false;

    this._map = null;
    this._filterControl = null;
    this._elDdlMarkers = null;
    this._arrTagGroups = [];
    this._arrMarkerGroups = [];
    this._arrSelectedTagIDs = [];

    this._width = null;
    this._height = null;
    this._isZoomable = null;
    this._maxZoomLevel = null;
    this._minZoomLevel = null;
    this._startPointMapLocation = null;
    this._mapType = null;
    this._markerBehavior = null;
    this._blShowControls = true;
    this._blShowLegend = true;
    this._blShowFilters = true;
    this._blShowDropDownList = true;
}
Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.Instance = null;
Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.prototype = {
    initialize: function () {
        Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.callBaseMethod(this, 'initialize');
        Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.Instance = this;

        // Add loaded handler.
        Sys.Application.add_load(Function.createDelegate(this, this.onLoaded));
    },
    dispose: function () {
        Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.callBaseMethod(this, 'dispose');
    },
    /// Called when all components have initialized.
    onLoaded: function () {
        // Determine start point.
        var latLng;

        if (this._startPointMapLocation) {
            var arrSplitStartPos = this._startPointMapLocation.split(",");

            latLng = new google.maps.LatLng(parseFloat(arrSplitStartPos[0]), parseFloat(arrSplitStartPos[1]));
        } else
            latLng = new google.maps.LatLng(52.422523, 5.339355);

        // Determine maptype.
        var mapType;

        switch (this._mapType) {
            case 0:
                mapType = google.maps.MapTypeId.ROADMAP;
                break;
            case 1:
                mapType = google.maps.MapTypeId.SATELLITE;
                break;
            case 2:
                mapType = google.maps.MapTypeId.TERRAIN;
                break;
            default:
                mapType = google.maps.MapTypeId.TERRAIN;
                break;
        }

        // Create MapOptions instance.
        var options = {
            zoom: this._minZoomLevel,
            center: latLng,
            mapTypeId: mapType,
            scrollwheel: false,
            mapTypeControlOptions: {
                position: google.maps.ControlPosition.TOP_LEFT
            }
        }

        // Create new GoogleMaps instance.        
        this._map = new google.maps.Map(this.get_element().children[0], options);

        // Set zoom behavior.
        var context = this;

        // Clamp zoom level on zoomend event to set values.
        google.maps.event.addListener(context._map, "zoom_changed", function () {
            cZoomLevel = context._map.getZoom();

            if (context._maxZoomLevel != null && cZoomLevel > context._maxZoomLevel)
                context._map.setZoom(context._maxZoomLevel);

            if (context._minZoomLevel != null && cZoomLevel < context._minZoomLevel)
                context._map.setZoom(context._minZoomLevel);
        });

        // Toggle the visibility of the controls.
        this.toggleVisibilityControls();

        // Load XML file
        this.loadXml();
    },
    /// Load the XML file.
    loadXml: function () {
        var context = this;

        this.downloadUrl("/_handlers/DataFileRequestHandler.ashx?strFile=GoogleMaps.xml", function (data, status) {
            // Parse XML data.
            var xml = context.parseXml(data);

            // Get nodes.
            var arrLegendItemNodes = xml.documentElement.getElementsByTagName("legendItem");
            var arrTagGroupNodes = xml.documentElement.getElementsByTagName("tagGroup");
            var arrMarkerGroupNodes = xml.documentElement.getElementsByTagName("markerGroup");

            // Create collection of TagGroup instances.
            if (context.get_ShowLegend()) {
                // Find legend unordered list element.
                var elLegendContainer = $("#legendContainer");

                // Create ul elements.
                var elUl = document.createElement("ul");

                // Append ul element.
                elLegendContainer.append(elUl);

                // Create elements for each legend item.
                for (var i = 0; i < arrLegendItemNodes.length; i++)
                    context.addLegendItemElements(elUl, arrLegendItemNodes[i]);
            }

            // Create collection of TagGroup instances.
            if (context.get_ShowFilters()) {
                for (var i = 0; i < arrTagGroupNodes.length; i++)
                    Array.add(context._arrTagGroups, $create(Mcw.Rijksoverheid.GoogleMaps.TagGroup, { Node: arrTagGroupNodes[i] }, null, null, context.addAndGetTagGroupElement()));
            }

            // Create collection of MarkerGroup instances.
            for (var i = 0; i < arrMarkerGroupNodes.length; i++)
                Array.add(context._arrMarkerGroups, $create(Mcw.Rijksoverheid.GoogleMaps.MarkerGroup, { Node: arrMarkerGroupNodes[i] }, null, null, context.addAndGetMarkerGroupElement()));

            // Create DropDownList with all Markers as options.
            if (context.get_ShowDropDownList())
                context.createDropDownList(context._arrMarkerGroups);
        });
    },
    downloadUrl: function (url, callback) {
        var context = this;

        var request = window.ActiveXObject ?
            new ActiveXObject('Microsoft.XMLHTTP') :
            new XMLHttpRequest;

        request.onreadystatechange = function () {
            if (request.readyState == 4) {
                request.onreadystatechange = context.doNothing;

                callback(request.responseText, request.status);
            }
        };

        request.open('GET', url, true);
        request.send(null);
    },
    parseXml: function (str) {
        if (window.ActiveXObject) {
            var doc = new ActiveXObject('Microsoft.XMLDOM');
            doc.loadXML(str);

            return doc;
        } else if (window.DOMParser) {
            return (new DOMParser).parseFromString(str, 'text/xml');
        }
    },
    doNothing: function () { },
    /// Creates and adds html elements for a legend item.
    addLegendItemElements: function (elUl, node) {
        // Create elements.
        var elLi = document.createElement("li");
        var elImg = document.createElement("img");
        var elSpan = document.createElement("span");

        // Set element properties.
        elImg.setAttribute("src", "/_images/googleMaps/marker" + node.getAttribute("id") + ".png");
        elImg.setAttribute("alt", "Marker " + node.getAttribute("id"));
        elSpan.innerHTML = node.getAttribute("name");

        // Append elements.
        elLi.appendChild(elImg);
        elLi.appendChild(elSpan);
        elUl.appendChild(elLi);
    },
    /// Add and Get TagGroupElements.
    addAndGetTagGroupElement: function () {
        var elFilterControlsContainer = $get("filterControlsContainer");

        // Create containing div element.
        var elContainer = document.createElement("div");
        $(elContainer).addClass("filtersContainer");

        // Create header element.
        var elHeader = document.createElement("h3");
        var elHeaderInner = document.createElement("a");

        // Create unordered list element.
        var elTags = document.createElement("ul");

        // Append elements.
        elHeader.appendChild(elHeaderInner);
        elContainer.appendChild(elHeader);
        elContainer.appendChild(elTags);
        elFilterControlsContainer.appendChild(elContainer);

        // Return reference to container element.
        return elContainer;
    },
    /// Add and Get MarkerGroupElements.
    addAndGetMarkerGroupElement: function () {
        // Create required elements.
        var elContainer = document.createElement("div");

        return elContainer;
    },
    /// Check zoom level of the google map.
    /// Client cannot exceed a zoomlevel of 10.
    checkZoomLevel: function () {
        czoomlevel = this._map.getZoom();

        if (czoomlevel > 10) {
            this._map.setZoom(10);
        }
    },
    /// 
    toggleSelectedFilter: function (intTagID) {
        // Add or remove tag for array.
        if (Array.contains(this._arrSelectedTagIDs, intTagID))
            Array.remove(this._arrSelectedTagIDs, intTagID);
        else
            Array.add(this._arrSelectedTagIDs, intTagID);

        // Get activate MarkerGroups by checking if it's related Tags matches the selected Tags.
        var arrActiveMarkerGroups = this.getActiveMarkerGroups();

        // Loop MarkerGroups to check if it's related Tags matches the selected Tags.
        for (var j = 0; j < this._arrMarkerGroups.length; j++) {
            // Show or hide all Markers in a Group according if a Group is active or not.
            if (Array.contains(arrActiveMarkerGroups, this._arrMarkerGroups[j]))
                this._arrMarkerGroups[j].showMarkerGroupOnMap(true);
            else
                this._arrMarkerGroups[j].showMarkerGroupOnMap(false);
        }

        // Recreate DropDownList and it's options.
        this.createDropDownList(arrActiveMarkerGroups);
    },
    /// Gets the activate MarkerGroups by checking if it's related Tags matches the selected Tags.
    getActiveMarkerGroups: function () {
        var blGroupTagsMatchSelectedTags = null;
        var arrActiveMarkerGroups = [];

        // Loop MarkerGroups to check if it's related Tags matches the selected Tags.
        for (var j = 0; j < this._arrMarkerGroups.length; j++) {
            blGroupTagsMatchSelectedTags = true;

            // Set boolean to false if a MarkerGroup related Tag isn't a currently a selected Tag 
            for (var k = 0; k < this._arrMarkerGroups[j]._arrTagIDs.length; k++)
                if (!Array.contains(this._arrSelectedTagIDs, this._arrMarkerGroups[j]._arrTagIDs[k]))
                    blGroupTagsMatchSelectedTags = false;

            // Add MarkerGroup to the Array which is used to create the DropDownList.
            if (blGroupTagsMatchSelectedTags == true)
                Array.add(arrActiveMarkerGroups, this._arrMarkerGroups[j]);
        }

        return arrActiveMarkerGroups;
    },
    /// Creates the dropdownlist with all the markers as select options.
    /// Sets the searchable options for the dropdownlist.
    /// Sets the event handler for when the selection changes.
    createDropDownList: function (arrMarkerGroups) {
        var context = this;

        // Create select element.
        this._elDdlMarkers = document.createElement('select');

        // Add change event handler in order to set the selected marker is active.
        $(this._elDdlMarkers).change(function () {
            $("option:selected").each(function () {
                for (var i = 0; i < context._arrMarkerGroups.length; i++) {
                    for (var k = 0; k < context._arrMarkerGroups[i]._arrMarkers.length; k++) {
                        if (context._arrMarkerGroups[i]._arrMarkers[k]._intID == parseInt($(this).attr("value")))
                            context._arrMarkerGroups[i]._arrMarkers[k].set_IsActive(true);
                        else
                            context._arrMarkerGroups[i]._arrMarkers[k].set_IsActive(false);
                    }
                }
            });
        }).change();

        // Remove previously added select element.
        $('#ddlMarkersContainer').find("select").remove();

        // Add the given markers as select options.
        this.appendSelectOptions(arrMarkerGroups);

        // Append the select control to the container.
        $('#ddlMarkersContainer').append(this._elDdlMarkers);

        // Set the searchable properties of the dropdownlist.
        $(this._elDdlMarkers).searchable({
            maxListSize: 200, 					        // if list size are less than maxListSize, show them all
            maxMultiMatch: 200, 					        // how many matching entries should be displayed
            exactMatch: false, 					        // Exact matching on search
            wildcards: true, 					        // Support for wildcard characters (*, ?)
            ignoreCase: true, 					        // Ignore case sensitivity
            latency: 200, 						        // how many millis to wait until starting search
            warnMultiMatch: 'Top {0} resultaten ...',   // string to append to a list of entries cut short by maxMultiMatch 
            warnNoMatch: 'Geen resultaten gevonden', 	// string to show in the list when no entries match
            zIndex: 'auto'							    // zIndex for elements generated by this plugin
        });
    },
    /// Adds all markers of all groups as select options in the dropdownlist.
    appendSelectOptions: function (arrMarkerGroups) {
        // Append default option.
        this.appendSelectOption("0", "- Geen selectie -");

        for (var i = 0; i < arrMarkerGroups.length; i++) {
            // Get all markers in group.
            for (var j = 0; j < arrMarkerGroups[i]._arrMarkers.length; j++) {
                // Append option to the dropdownlist.
                this.appendSelectOption(arrMarkerGroups[i]._arrMarkers[j]._intID, arrMarkerGroups[i]._arrMarkers[j]._strName);
            }
        }
    },
    /// Appends select option to the dropdownlist.
    appendSelectOption: function (intID, strName) {
        // Append option to the dropdownlist.
        $(this._elDdlMarkers).append("<option value=\"" + intID + "\">" + strName + "</option>");
    },
    // Toggles the visible of the controls.
    toggleVisibilityControls: function () {
        // Get references.
        var ddlMarkersContainer = $("#ddlMarkersContainer");
        var filterControlsContainer = $("#filterControlsContainer");
        var legendContainer = $("#legendContainer");

        if (!this._blShowDropDownList)
            ddlMarkersContainer.hide();

        if (!this._blShowFilters)
            filterControlsContainer.hide();

        if (!this._blShowLegend)
            legendContainer.hide();

        // Hide containers if specified.
        if (this._blShowControls == false) {
            ddlMarkersContainer.hide('slow');
            filterControlsContainer.hide('slow');
            legendContainer.hide('slow');
        } else {
            if (this._blShowDropDownList)
                ddlMarkersContainer.show('slow');

            if (this._blShowFilters)
                filterControlsContainer.show('slow');

            if (this._blShowLegend)
                legendContainer.show('slow');
        }

        // Show or hide Google Maps controls.
        if (this._map) {
            if (this._blShowControls == false)
                this._map.setOptions({ disableDefaultUI: true });
            else
                this._map.setOptions({ disableDefaultUI: false });
        }

        // Recreate dropdownlist for correct displaying.
        this.createDropDownList(this.getActiveMarkerGroups());
    },

    // Properties - get / set.
    get_SelectedTagIDs: function () {
        return this._arrSelectedTagIDs;
    },
    get_Map: function () {
        return this._map;
    },
    get_Width: function () {
        return this._width;
    },
    set_Width: function (value) {
        if (this._width != value) {
            this._width = value;
        }
    },
    get_Height: function () {
        return this._height;
    },
    set_Height: function (value) {
        if (this._height != value) {
            this._height = value;
        }
    },
    get_IsZoomable: function () {
        return this._isZoomable;
    },
    set_IsZoomable: function (value) {
        if (this._isZoomable != value) {
            this._isZoomable = value;
        }
    },
    get_MaxZoomLevel: function () {
        return this._maxZoomLevel;
    },
    set_MaxZoomLevel: function (value) {
        if (this._maxZoomLevel != value) {
            this._maxZoomLevel = value;
        }
    },
    get_MinZoomLevel: function () {
        return this._minZoomLevel;
    },
    set_MinZoomLevel: function (value) {
        if (this._minZoomLevel != value) {
            this._minZoomLevel = value;
        }
    },
    get_StartPointMapLocation: function () {
        return this._albums;
    },
    set_StartPointMapLocation: function (value) {
        if (this._startPointMapLocation != value) {
            this._startPointMapLocation = value;
        }
    },
    get_DefaultMapType: function () {
        return this._mapType;
    },
    set_DefaultMapType: function (value) {
        if (this._mapType != value) {
            this._mapType = value;
        }
    },
    get_MarkerBehavior: function () {
        return this._markerBehavior;
    },
    set_MarkerBehavior: function (value) {
        if (this._markerBehavior != value) {
            this._markerBehavior = value;
        }
    },
    get_ShowControls: function () {
        return this._blShowControls;
    },
    set_ShowControls: function (value) {
        if (this._blShowControls != value) {
            this._blShowControls = value;

            this.toggleVisibilityControls();
        }
    },
    get_ShowLegend: function () {
        return this._blShowLegend;
    },
    set_ShowLegend: function (value) {
        if (this._blShowLegend != value) {
            this._blShowLegend = value;
        }
    },
    get_ShowFilters: function () {
        return this._blShowFilters;
    },
    set_ShowFilters: function (value) {
        if (this._blShowFilters != value) {
            this._blShowFilters = value;
        }
    },
    get_ShowDropDownList: function () {
        return this._blShowDropDownList;
    },
    set_ShowDropDownList: function (value) {
        if (this._blShowDropDownList != value) {
            this._blShowDropDownList = value;
        }
    }
}

Mcw.Rijksoverheid.GoogleMaps.MapViewerControl.registerClass("Mcw.Rijksoverheid.GoogleMaps.MapViewerControl", Sys.UI.Control);

/// Functions below can be used to store viewer state between postbacks. Not implemented at the moment.
function CreateCookie(strName, strValue, intDays) {
    if (intDays) {
        var date = new Date();
        date.setTime(date.getTime() + (intDays * 24 * 60 * 60 * 1000));

        var strExpires = "; expires=" + date.toGMTString();
    } else
        var strExpires = "";

    document.cookie = strName + "=" + strValue + strExpires + "; path=/";
}
function ReadCookie(strName) {
    var strNameEQ = strName + "=";
    var arr = document.cookie.split(';');

    for (var i = 0; i < ca.length; i++) {
        var c = arr[i];

        while (c.charAt(0) == ' ')
            c = c.substring(1, c.length);

        if (c.indexOf(strNameEQ) == 0)
            return c.substring(strNameEQ.length, c.length);
    }

    return null;
}
function EraseCookie(strName) {
    CreateCookie(strName, "", -1);
}
