﻿/// <reference name="MicrosoftAjax.js"/>
/// <reference path="VEJS/VeJavaScriptIntellisenseHelper.js" />

var velocityList = new Array();

Type.registerNamespace("Shoothill.Mapping.ServerControl.Client");


Shoothill.Mapping.ServerControl.Client.MappingClientControl = function(element) {
    Shoothill.Mapping.ServerControl.Client.MappingClientControl.initializeBase(this, [element]);

    this._veMap = null;
    this._veMapId = '';
    this._hostURL = new Array();
    this._dataSourceLayer = null;
    this._baseLayer = null;
    this._currentShape = null;
    this._currentIndex = 0;

    this._pinData = null;
    //this._shapePointData = null;

    this._zoomLevel = 4;
    this._zoomLevelSet = false;
    this._clientZoomed = false;

    this._latitude = 0;
    this._longitude = 0;
    this._latLongSet = false;

    this._mapStyle = "r";
    this._mapStyleSet = false;

    this._mapFixed = false;
    this._mapFixedSet = false;

    this._mapMode = VEMapMode.Mode2D;
    this._mapModeSet = false;

    this._skipLoadingShapes = false;
    this._hideInfoboxFunction = null;

    this._showSwitch = true;
    this._showSwitchSet = false;
    
    this._showDashboard = true;

    this._tileBuffer = 0;
    this._tileBufferSet = false;

    this._singlePinIcon = 0;
    this._singlePinIconSet = false;
    this._clusteredPinIcon = 0;
    this._clusteredPinIconSet = false;

    this._persistPopup = false;
    this._persistPopupSet = false;

    this._logging = true;

    this._prm = null;

    this._dataItems = null;

    this._clientMethods = null;

    this._dataHash = null;

    this.currentMouseEvent = null;

    //this.blueBalloon  = new Balloon;
    this.blueBalloon = null;

    this.resizing = false;

    this._controlID = "";
    this._session = "";
    this._pageID = "";

    this._enableTileServer = false;

    this._showPoints = true;
    this._showLines = true;
    this._showRegions = true;

    this._tileGenerators = null;

    this._cacheDataPerSession = true;

    this._enableMouseEvents = true;

}


Shoothill.Mapping.ServerControl.Client.MappingClientControl.prototype = {
    initialize: function() {
        Shoothill.Mapping.ServerControl.Client.MappingClientControl.callBaseMethod(this, 'initialize');

        var s = window.location.href.split('/');
        s.splice(s.length - 1, 1);
        this._hostURL = s.join('/') + '/';

        //       this.blueBalloon.parent = this;
        //       this.blueBalloon.balloonImage     = '~/IconHandler.axd?icon=balloon&type=popup';
        //       this.blueBalloon.stem = true;
        //       this.blueBalloon.stemOverlap = 3;

        //      // A stem for each of the four orientations
        //      this.blueBalloon.upLeftStem    = '~/IconHandler.axd?icon=up_left&type=popup';
        //      this.blueBalloon.downLeftStem  = '~/IconHandler.axd?icon=down_left&type=popup';
        //      this.blueBalloon.upRightStem   = '~/IconHandler.axd?icon=up_right&type=popup';
        //      this.blueBalloon.downRightStem = '~/IconHandler.axd?icon=down_right&type=popup';
        //      this.blueBalloon.closeButton   = '~/IconHandler.axd?icon=close&type=popup';
        //      //this.blueBalloon.shadow = 40;

        // Add custom initialization here  
        this._prm = Sys.WebForms.PageRequestManager.getInstance();

        this._pageLoadingHandler = Function.createDelegate(this, this.pageLoadingEvent);

        this._prm.add_pageLoading(this._pageLoadingHandler);

        this.decodeMapStyle();

        this.get_element().style.position = "relative";
        this._veMapId = this.get_element().id;
        this._veMap = new VEMap(this._veMapId);


        //patch up VE events
        //map events
        //this._veMap.onLoadMap = Function.createDelegate(this, this.mapOnLoadEvent);
        this._veMap.AttachEvent("onchangemapstyle", Function.createDelegate(this, this.mapStyleChangeEvent));
        this._veMap.AttachEvent("onchangeview", Function.createDelegate(this, this.mapViewChangeEvent));
        this._veMap.AttachEvent("onstartpan", Function.createDelegate(this, this.mapPanStartEvent));
        this._veMap.AttachEvent("onendpan", Function.createDelegate(this, this.mapPanEndEvent));
        this._veMap.AttachEvent("onstartzoom", Function.createDelegate(this, this.mapZoomStartEvent));
        this._veMap.AttachEvent("onendzoom", Function.createDelegate(this, this.mapZoomEndEvent));
        this._veMap.AttachEvent("oninitmode", Function.createDelegate(this, this.mapModeInitEvent));
        this._veMap.AttachEvent("onmodenotavailable", Function.createDelegate(this, this.mapModeNotAvailableEvent));
        this._veMap.AttachEvent("onobliqueenter", Function.createDelegate(this, this.mapObliqueEnterEvent));
        this._veMap.AttachEvent("onobliquechange", Function.createDelegate(this, this.mapObliqueChangeEvent));
        this._veMap.AttachEvent("onobliqueleave", Function.createDelegate(this, this.mapObliqueLeaveEvent));
        this._veMap.AttachEvent("onerror", Function.createDelegate(this, this.mapErrorEvent));

        //mouse events

        this._veMap.AttachEvent("onmouseover", Function.createDelegate(this, this.mouseEvent));

        //Overloads
        VEShape.prototype.RecordsInCluster = 0;
        VEShape.prototype.Point = "";
        VEShapeLayer.prototype.ssid = "";
        VEShapeLayer.mouseEvent = null;


        //myMap = this._veMap;
        //load the map        
        this._veMap.LoadMap(new VELatLong(this._latitude, this._longitude), this._zoomLevel, this._mapStyle, this._mapFixed, this._mapMode, this._showSwitch, this._tileBuffer);
        if (this._showDashboard == true) {
            this._veMap.ShowDashboard();
        }
        else {
            this._veMap.HideDashboard();
        }

        this._veMap.Resize();
        //debugger;
        if (window.attachEvent) {
            window.attachEvent("onresize", Function.createDelegate(this, this.mapResize));
        }
        else {
            window.addEventListener("resize", Function.createDelegate(this, this.mapResize));
        }

        this._veMap.AttachEvent("onresize", Function.createDelegate(this, this.mapResizeEvent));

        //if the user has enabled the tile server
        if (this._enableTileServer && this._tileGenerators != null) {
            //debugger;

            var pageID = this.get_pageID();
            var controlID = this.get_controlID();
            var sessionID = "";

            if (this._cacheDataPerSession)
                sessionID = this.get_session();

            for (var tileGenIdx = 0; tileGenIdx < this._tileGenerators.length; tileGenIdx++) {
                //"http://www.myserver.com/myvelocityapp/TileHandler.axd?pageid=ASP.test_aspx&id=VELocityControl1&genid=zyx987&session=abc123style=%1&quad=%4";

                var tileGenerator = this._tileGenerators[tileGenIdx];

                var tileSourceSpec = new VETileSourceSpecification("VE-LocityTileLayer_" + tileGenerator.ID, this._hostURL + "TileHandler.axd?pageid=" + pageID + "&id=" + controlID + "&genid=" + tileGenerator.ID + "&session=" + sessionID + "&style=%1&quad=%4");
                tileSourceSpec.NumServers = 1;
                tileSourceSpec.ZIndex = tileGenerator.ZIndex;

                this._veMap.AddTileLayer(tileSourceSpec, true);
            }
        }

        if (this._persistPopup)
            this.disableHideInfoBox();

        //this._veMap.ClearInfoBoxStyles();
        this._clientMethods = new Shoothill.Mapping.ServerControl.Client.MappingClientVEMap(this);

        //myMap = this._veMap;
        velocityList.push(this);

        this.log('loaded map');

    },

    refreshTileLayers: function() {

        var tileLayerCount = this._veMap.GetTileLayerCount();

        for (var index = 0; index < tileLayerCount; index++) {

            var tileLayer = this._veMap.GetTileLayerByIndex(index);

            this._veMap.DeleteTileLayer(tileLayer.ID);

            var map = this._veMap;
            setTimeout(function() {
                map.AddTileLayer(tileLayer);
            }, 1000);
        }
    },

    mapResize: function() {
        try {
            this._veMap.Resize();
        }
        catch (exception) {
        }
        //this.resizing = true;
        //this._veMap.Resize("600","600");
    },

    //Public method to get instance of this map
    GetMapInstance: function() {
        return this._veMap;
    },

    //decode the map style, if it's been set to something whacky
    decodeMapStyle: function() {
        if (this._mapStyle !== "r" &&
             this._mapStyle !== "a" &&
             this._mapStyle !== "h" &&
             this._mapStyle !== "o") {
            switch (this._mapStyle) {
                default:
                case 1:
                    this._mapStyle = "r";
                    break;
                case 2:
                    this._mapStyle = "a";
                    break;
                case 3:
                    this._mapStyle = "h";
                    break;
                case 4:
                    this._mapStyle = "o";
                    break;
            }
        }
    },

    pageLoadingEvent: function(sender, args) {
        this.log('pageLoadingEvent *************************************************************************');
        //get the data items meant for us
        var dataItems = args.get_dataItems()[this.get_element().id];

        //if these data items are different to last time
        //if ( this._dataItems != dataItems )
        //{        
        //store the data items
        //this._dataItems = dataItems;

        //deserialise the data items
        var data = Sys.Serialization.JavaScriptSerializer.deserialize(dataItems);

        if (this._clientMethods != null)
            this._clientMethods.executeCommands(data.commanddictionary);

        //populate the controls data only if there are no commands to run           
        //            if(data.commanddictionary.length == 0)
        this.populateData(data);
        //}
        //return true;        
    },



    populateData: function(data) {
        this.log('populateData');

        //go through all properties
        if (data['zoomlevel'] != null) {
            this.set_zoomLevel(data['zoomlevel']);
        }
        if (data['latitude'] != null) {
            this.set_latitude(data['latitude']);
        }
        if (data['longitude'] != null) {
            this.set_longitude(data['longitude']);
        }
        if (data['mapstyle'] != null) {
            this.set_mapStyle(data['mapstyle']);
        }
        if (data['mapfixed'] != null) {
            this.set_mapFixed(data['mapfixed']);
        }
        if (data['mapmode'] != null) {
            this.set_mapMode(data['mapmode']);
        }
        if (data['showswitch'] != null) {
            this.set_showSwitch(data['showswitch']);
        }
        if (data['showdashboard'] != null) {
            this.set_showDashboard(data['showdashboard']);
        }
        if (data['tilebuffer'] != null) {
            this.set_tileBuffer(data['tilebuffer']);
        }
        if (data['singlePinIcon'] != null) {
            this.set_singlePinIcon(data['singlePinIcon']);
        }
        if (data['clusteredPinIcon'] != null) {
            this.set_clusteredPinIcon(data['clusteredPinIcon']);
        }

        this._mapStyle = this._veMap.GetMapStyle();

        //check whether the data has changed
        var dataChanged = false;

        if (data['dataHash'] != null) {
            this.log('current dataHash: ' + this._dataHash + ', new dataHash: ' + data['dataHash']);

            if (this._dataHash == null || this._dataHash != data['dataHash'])
                dataChanged = true;

            this._dataHash = data['dataHash'];
        }

        //load the pins
        this.loadShapes(data['clusterData'], this._zoomLevelSet || this._clientZoomed || dataChanged);

        this._clientZoomed = false; //clear this flag

        //load point data
        this.loadPointData(data['pointData']);

        //apply changes to map
        if (this._veMap != null) {
            //if the map style isn't birdseye
            if (this._veMap.GetMapStyle() != "o") {
                if (this._latLongSet && this._zoomLevelSet) {
                    this._veMap.SetCenterAndZoom(new VELatLong(this.get_latitude(), this.get_longitude()), this.get_zoomLevel());
                    this._latLongSet = false;
                    this._zoomLevelSet = false;
                }
                else if (this._latLongSet) {
                    //this._veMap.PanToLatLong(new VELatLong(this.get_latitude(), this.get_longitude()));
                    this._latLongSet = false;
                }
                else if (this._zoomLevelSet) {
                    this._veMap.SetZoomLevel(this.get_zoomLevel());
                    this._zoomLevelSet = false;
                }
            }
            else {
                //birdseye mode updating
            }
        }

    },



    loadPointData: function(pointData) {
        this.log('loadPointData');

        //if we have some data to show in the pin
        if (pointData != null) {

            this.log('got point data');


            /*
            
            -		pointData	{...}	Object
            -		BoundsExtent	{...}	Object
            -		NW	{...}	Object
            Latitude	-90	Long
            Longitude	180	Long
            -		SE	{...}	Object
            Latitude	90	Long
            Longitude	-180	Long
            Details	"POIID: 1
            CategoryID: 1
            Boundary: 
            Details: East Putney
            "	String
            IsClustered	false	Boolean
            -		Loc	{...}	Object
            Latitude	51.4588203430176	Double
            Longitude	-0.210969999432564	Double
            Title	"UNKNOWN"	String
            TotalRecords	23600	Long

            
            */

            if (this._currentShape != null) {
                this.log('setting current shape data...');

                //debugger;      

                var titleDiv = document.getElementById('Popup_ShoothillTitle');
                var descriptionDiv = document.getElementById('Popup_ShoothillDescription');
                //var titleDiv = document.createElement("div");
                //titleDiv.id = this._currentShape.GetID() + '_ShoothillTitle';
                //var descriptionDiv = document.createElement("div");
                //descriptionDiv.id = this._currentShape.GetID() + '_ShoothillDescription';

                if (titleDiv != null) {
                    titleDiv.innerHTML = pointData.Title;
                    this._currentShape.SetTitle(titleDiv.outerHTML);
                }

                if (descriptionDiv != null) {
                    descriptionDiv.innerHTML = pointData.Details;

                    var ccmain = document.createElement("div");
                    Sys.UI.DomElement.addCssClass(ccmain, "Actions");
                    ccmain.id = "ccmain";
                    ccmain.style.position = "absolute";
                    ccmain.style.bottom = "0px";
                    ccmain.style.left = "0px";
                    ccmain.style.padding = "5px";
                    ccmain.style.backgroundColor = "#E4EDF3";
                    ccmain.style.width = "100%";

                    //Zoom Control Panel

                    var zoomPanel = document.createElement("div");

                    if (pointData.TotalRecords <= 1) {
                        var streetButton = document.createElement('a');
                        streetButton.innerHTML = 'street';
                        zoomPanel.appendChild(streetButton);
                        Sys.UI.DomElement.addCssClass(streetButton, "ActionButton");
                        $addHandler(streetButton, "click", Function.createDelegate(this, this.zoomStreet));

                        var cityButton = document.createElement('a');
                        cityButton.innerHTML = 'city';
                        zoomPanel.appendChild(cityButton);
                        Sys.UI.DomElement.addCssClass(cityButton, "ActionButton");
                        $addHandler(cityButton, "click", Function.createDelegate(this, this.zoomCity));

                        var regionButton = document.createElement('a');
                        regionButton.innerHTML = 'region';
                        zoomPanel.appendChild(regionButton);
                        Sys.UI.DomElement.addCssClass(regionButton, "ActionButton");
                        $addHandler(regionButton, "click", Function.createDelegate(this, this.zoomRegion));
                    }
                    else //Show All                    
                    {
                        var showAllButton = document.createElement('a');
                        showAllButton.innerHTML = 'Show All';
                        zoomPanel.appendChild(showAllButton);
                        Sys.UI.DomElement.addCssClass(showAllButton, "ActionButton");
                        $addHandler(showAllButton, "click", Function.createDelegate(this, this.showAll));
                    }

                    ccmain.appendChild(zoomPanel);

                    if (pointData.TotalRecords > 1) {
                        //Paging Panel

                        var pagingPanel = document.createElement("div");

                        //Enable Prev Button                                        
                        var prevButton = document.createElement('a');
                        prevButton.innerHTML = 'Previous';
                        pagingPanel.appendChild(prevButton);
                        Sys.UI.DomElement.addCssClass(prevButton, "ActionButton");
                        if (this._currentIndex > 0)
                            $addHandler(prevButton, "click", Function.createDelegate(this, this.previousRecord));
                        else
                            Sys.UI.DomElement.addCssClass(prevButton, "ButtonDisabled");


                        //Enable Next Button
                        var nextButton = document.createElement('a');
                        nextButton.innerHTML = 'Next';
                        pagingPanel.appendChild(nextButton);
                        Sys.UI.DomElement.addCssClass(nextButton, "ActionButton");
                        if (this._currentIndex < (pointData.TotalRecords - 1))
                            $addHandler(nextButton, "click", Function.createDelegate(this, this.nextRecord));
                        else
                            Sys.UI.DomElement.addCssClass(nextButton, "ButtonDisabled");


                        //Record Paging
                        var page = document.createElement('div');
                        page.style.position = "absolute";
                        page.style.right = "15px";
                        page.style.color = "black";
                        page.innerHTML = "Page " + (this._currentIndex + 1) + ' of ' + pointData.TotalRecords;
                        pagingPanel.appendChild(page);
                        Sys.UI.DomElement.addCssClass(page, "ActionButton");

                        ccmain.appendChild(pagingPanel);

                    }

                    descriptionDiv.appendChild(ccmain);

                    this._currentShape.SetDescription(descriptionDiv.outerHTML);

                    this.log('...finished setting current shape data');

                    //document.getElementById("contents").innerHTML = descriptionDiv.innerHTML;
                    //var ev = this.currentMouseEvent;
                    //ev.type = "mouseover";
                    //ev.srcElement = new Object();
                    //ev.srcElement.nodeType = 1;

                    //var img=document.getElementById("popup");
                    //img.style.height = descriptionDiv.offsetHeight;
                    //img.style.width = descriptionDiv.offsetWidth;
                    //var html = title + desc;
                    //var id = this._currentShape.GetID() + '_ShoothillDescription';
                    //this.blueBalloon.showTooltip(ev, 'load:' + id, 1)   ;
                    //debugger;
                    //this.showpopup(this.currentMouseEvent, descriptionDiv.innerHTML);                   

                    if (this._persistPopup)
                        this.disableHideInfoBox();
                }
            }
            else {
                this.log('current shape is null');
            }

        }
        else {
            this.log('no point data specified');
        }

    },

    showpopup: function(ev, title, desc) {
        try {
            ev.type = "mouseover";
            ev.srcElement = new Object();
            ev.srcElement.nodeType = 1;
            var html = title + desc;
            this.log('Showing balloon->' + html);
            this.blueBalloon.showTooltip(ev, html, 1)
        }
        catch (exception) {
            debugger;
            alert(exception);
        }
    },

    previousRecord: function() {
        this.log('previousRecord');
        this._skipLoadingShapes = true;
        this._currentIndex--;

        //        if ( this._currentShape != null )        
        //            document.getElementById(this._currentShape.GetID() + '_ShoothillTitle').innerText = 'Loading...';
        //        
        this.doPostBack(this.createEventArgs('previousRecordEvent', this.createDataSet()));

    },


    nextRecord: function() {
        this.log('nextRecord');
        this._skipLoadingShapes = true;
        this._currentIndex++;

        //        if ( this._currentShape != null )        
        //            document.getElementById(this._currentShape.GetID() + '_ShoothillTitle').innerText = 'Loading...';
        //        
        this.doPostBack(this.createEventArgs('nextRecordEvent', this.createDataSet()));

    },

    showAll: function() {
        this.log('showAll');

        if (this._currentShape != null) {
            var shapeID = this._currentShape.GetID();

            if (shapeID != null) {
                var clusterPoint = this._currentShape.Point;

                if (clusterPoint != null) {
                    this._veMap.SetMapView([new VELatLong(clusterPoint.Bounds.NW.Latitude,
                                                          clusterPoint.Bounds.NW.Longitude),
                                            new VELatLong(clusterPoint.Bounds.SE.Latitude,
                                                          clusterPoint.Bounds.SE.Longitude)]);
                }
            }
        }
    },

    zoomStreet: function() {
        if (this._currentShape != null) {
            var latlong = this._currentShape.GetPoints()[0];

            this._veMap.SetCenterAndZoom(latlong, 16);
        }
    },

    zoomCity: function() {
        if (this._currentShape != null) {
            var latlong = this._currentShape.GetPoints()[0];

            this._veMap.SetCenterAndZoom(latlong, 11);
        }
    },

    zoomRegion: function() {
        if (this._currentShape != null) {
            var latlong = this._currentShape.GetPoints()[0];

            this._veMap.SetCenterAndZoom(latlong, 6);
        }
    },

    loadShapes: function(pinData, changed) {
        //If we are trying to load the shapes from a mouse event return as there is no need to refresh the shapes
        //as the view hasnt changed.
        if (this._skipLoadingShapes) {
            this._skipLoadingShapes = false;
            return false;
        }

        this.log('loadShapes');

        if (pinData != null) {
            //debugger;

            this.log('got data for ' + pinData.length + ' shapes');

            if (this._dataSourceLayer != null) {
                //if we zoomed
                if (changed) {
                    this.log('changed, deleting all shapes in layer, setting current shape to null');

                    //delete all the shapes and re-add them
                    this._dataSourceLayer.DeleteAllShapes();

                    //trash this data
                    this._currentShape = null;
                    this._currentIndex = 0;
                }
            }
            else {
                this.log('adding new shape layer');
                this._dataSourceLayer = new VEShapeLayer();
                this._dataSourceLayer.SetTitle = "DataSource";

                this._veMap.AddShapeLayer(this._dataSourceLayer);

                this.log('adding new base shape layer');
                this._baseLayer = new VEShapeLayer();
                this._baseLayer.SetTitle = "Base";

                this._veMap.AddShapeLayer(this._baseLayer);
            }

            var shapeList = new Array();

            for (var pinIndex in pinData) {
                var point = pinData[pinIndex];

                //is this point already in the shape point data

                //if it isn't, add it

                //if (!found)
                {
                    //this.log('pin ' + pinIndex + ' not found on map, adding...');

                    var shapeType;
                    var shape;

                    if ((point.GeoType <= 1) && this._showPoints) {
                        shapeType = VEShapeType.Pushpin;
                        shape = new VEShape(shapeType, new VELatLong(point.Centroid.Latitude, point.Centroid.Longitude));
                    }
                    else {
                        //debugger;

                        if ((point.GeoType == 2) && this._showLines)
                            shapeType = VEShapeType.Polyline;
                        else if (this._showRegions)
                            shapeType = VEShapeType.Polygon;

                        var pointArray = new Array();

                        for (var pointIndex in point.Points) {
                            pointArray.push(new VELatLong(point.Points[pointIndex].Latitude, point.Points[pointIndex].Longitude));
                        }

                        shape = new VEShape(shapeType, pointArray);
                    }

                    shape.RecordsInCluster = point.NumberOfRecordsInCluster;

                    var pinIcon;
                    var icon;
                    var fullIconURL;
                    if (shape.RecordsInCluster > 1) {
                        pinIcon = this.get_clusteredPinIcon();
                        var records = shape.RecordsInCluster;
                        icon = this._hostURL + "IconHandler.axd?icon=" + pinIcon + "&type=cluster&records=" + records;
                        if (this.get_clusteredPinIcon() != null) {
                            fullIconURL = this.getPNGFix(icon);
                            shape.SetCustomIcon(fullIconURL);
                        }
                    }
                    else {
                        pinIcon = this.get_singlePinIcon();
                        icon = this._hostURL + "IconHandler.axd?icon=" + pinIcon + "&type=single&records=1"
                        if (this.get_singlePinIcon() != null) {
                            fullIconURL = this.getPNGFix(icon);
                            shape.SetCustomIcon(fullIconURL);
                        }
                    }

                    //shape.SetCustomIcon("~/IconHandler.axd?icon=blank");           

                    shape.Point = point;

                    shapeList.push(shape);
                    //this._shapePointData[shape.GetID()] = point;
                }
            }

            this._dataSourceLayer.DeleteAllShapes();
            this._dataSourceLayer.AddShape(shapeList);
        }
    },

    boundsOverlap: function(bounds1, bounds2) {
    },

    //control properties

    //zoomLevel    
    get_zoomLevel: function() {
        return this._zoomLevel;
    },

    set_zoomLevel: function(value) {
        if (this._zoomLevel !== value) {
            this._zoomLevel = value;
            this.raisePropertyChanged('zoomLevel');

            this._zoomLevelSet = true;
        }
    },

    //latitude
    get_latitude: function() {
        return this._latitude;
    },

    set_latitude: function(value) {
        if (this._latitude !== value) {
            this._latitude = value;
            this.raisePropertyChanged('latitude');

            this._latLongSet = true;
        }
    },

    //longitude 
    get_longitude: function() {
        return this._longitude;
    },

    set_longitude: function(value) {
        if (this._longitude !== value) {
            this._longitude = value;
            this.raisePropertyChanged('longitude');

            this._latLongSet = true;
        }
    },

    //mapStyle
    get_mapStyle: function() {
        return this._mapStyle;
    },

    set_mapStyle: function(value) {
        if (this._mapStyle !== value) {
            this._mapStyle = value;

            this.decodeMapStyle();

            this.raisePropertyChanged('mapStyle');

            this._mapStyleSet = true;
        }
    },

    //mapFixed
    get_mapFixed: function() {
        return this._mapFixed;
    },

    set_mapFixed: function(value) {
        if (this._mapFixed !== value) {
            this._mapFixed = value;
            this.raisePropertyChanged('mapFixed');

            this._mapFixedSet = true;
        }
    },

    //mapMode 
    get_mapMode: function() {
        return this._mapMode;
    },

    set_mapMode: function(value) {
        if (this._mapMode !== value) {
            this._mapMode = value;
            this.raisePropertyChanged('mapMode');

            this._mapModeSet = true;
        }
    },

    //showSwitch
    get_showSwitch: function() {
        return this._showSwitch;
    },

    set_showSwitch: function(value) {
        if (this._showSwitch !== value) {
            this._showSwitch = value;
            this.raisePropertyChanged('showSwitch');

            this._showSwitchSet = true;
        }
    },

    //showDashboard
    get_showDashboard: function() {
        return this._showDashboard;
    },

    set_showDashboard: function(value) {
        if (this._showDashboard !== value) {
            this._showDashboard = value;
            this.raisePropertyChanged('showDashboard');
        }
    },

    //tileBuffer
    get_tileBuffer: function() {
        return this._tileBuffer;
    },

    set_tileBuffer: function(value) {
        if (this._tileBuffer !== value) {
            this._tileBuffer = value;
            this.raisePropertyChanged('tileBuffer');

            this._tileBufferSet = true;
        }
    },

    //SinglePinIcnons
    get_singlePinIcon: function() {
        if (this._singlePinIcon != null && this._singlePinIcon != "")
            return this._singlePinIcon;
        else
            return null;
    },

    set_singlePinIcon: function(value) {
        if (this._singlePinIcon !== value) {
            this._singlePinIcon = value;
            this.raisePropertyChanged('singlePinIcon');

            this._singlePinIconSet = true;
        }
    },

    //ClusteredPinIcnons
    get_clusteredPinIcon: function() {
        if (this._clusteredPinIcon != null && this._clusteredPinIcon != "")
            return this._clusteredPinIcon;
        else
            return null;
    },

    set_clusteredPinIcon: function(value) {
        if (this._clusteredPinIcon !== value) {
            this._clusteredPinIcon = value;
            this.raisePropertyChanged('clusteredPinIcon');

            this._clusteredPinIconSet = true;
        }
    },

    //ClusteredPinIcnons
    get_persistPopup: function() {
        if (this._persistPopup != null)
            return this._persistPopup;
        else
            return null;
    },

    set_persistPopup: function(value) {
        if (this._persistPopup !== value) {
            this._persistPopup = value;
            this.raisePropertyChanged('persistPopup');

            this._persistPopupSet = true;
        }
    },

    //session
    get_session: function() {
        return this._session;
    },

    set_session: function(value) {
        if (this._session !== value) {
            this._session = value;
            this.raisePropertyChanged('session');
        }
    },

    //control id
    get_controlID: function() {
        return this._controlID;
    },

    set_controlID: function(value) {
        if (this._controlID !== value) {
            this._controlID = value;
            this.raisePropertyChanged('controlID');
        }
    },

    //control id
    get_pageID: function() {
        return this._pageID;
    },

    set_pageID: function(value) {
        if (this._pageID !== value) {
            this._pageID = value;
            this.raisePropertyChanged('pageID');
        }
    },

    //points display
    get_showPoints: function() {
        return this._showPoints;
    },

    set_showPoints: function(value) {
        if (this._showPoints !== value) {
            this._showPoints = value;
            this.raisePropertyChanged('showPoints');
        }
    },

    //line display
    get_showLines: function() {
        return this._showLines;
    },

    set_showLines: function(value) {
        if (this._showLines !== value) {
            this._showLines = value;
            this.raisePropertyChanged('showLines');
        }
    },

    //line display
    get_showRegions: function() {
        return this._showRegions;
    },

    set_showRegions: function(value) {
        if (this._showRegions !== value) {
            this._showRegions = value;
            this.raisePropertyChanged('showRegions');
        }
    },

    //tile server
    get_enableTileServer: function() {
        return this._enableTileServer;
    },

    set_enableTileServer: function(value) {
        if (this._enableTileServer !== value) {
            this._enableTileServer = value;
            this.raisePropertyChanged('enableTileServer');
        }
    },

    //tile generators
    get_tileGenerators: function() {
        return this._tileGenerators;
    },

    set_tileGenerators: function(value) {
        if (this._tileGenerators !== value) {
            this._tileGenerators = value;
            this.raisePropertyChanged('tileGenerators');
        }
    },

    //cache data per session
    get_cacheDataPerSession: function() {
        return this._cacheDataPerSession;
    },

    set_cacheDataPerSession: function(value) {
        if (this._cacheDataPerSession !== value) {
            this._cacheDataPerSession = value;
            this.raisePropertyChanged('cacheDataPerSession');
        }
    },


    getPNGFix: function(icon) {
        var retval;
        if (Sys.Browser.name == "Microsoft Internet Explorer" && Sys.Browser.version < 7) {
            retval = "<img src='IconHandler.axd?icon=blank' style='filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\"" + icon + "\", " +
            "sizingMethod=\"image\" );' />";
        }
        else
            retval = icon;

        return retval;
    },

    //events    

    mouseEvent: function(e) {
        if (this._enableMouseEvents && e.elementID != null) {
            //debugger;

            this.log('mouseEvent fired for shape ' + e.elementID);
            this.currentMouseEvent = e;
            //            if ( this._currentShape != this._veMap.GetShapeByID(e.elementID))
            //            {            
            this._currentShape = this._veMap.GetShapeByID(e.elementID);
            this._currentIndex = 0;
            //            }


            //Load in the HTML here so that we can reference it later on when we are filling the data    
            //var contentsDiv = document.createElement('div');
            //contentsDiv.id = "contents";
            var titleDiv = "<div id=" + 'Popup_ShoothillTitle' + ">Loading...</div><br/>";
            var descDiv;
            if (this._currentShape.RecordsInCluster > 1)
                descDiv = "<div class='shoothilldescription' id='" + "Popup_ShoothillDescription'>Cluster 1 - " + this._currentShape.RecordsInCluster + " records" + "</div>";
            else
                descDiv = "<div class='shoothilldescription' id='" + "Popup_ShoothillDescription'></div>";


            this._currentShape.SetTitle(titleDiv);
            this._currentShape.SetDescription(descDiv);

            this._skipLoadingShapes = true;

            //this.disableHideInfobox();

            this.doPostBack(this.createEventArgs('mapMouseEvent', this.createDataSet()));
            //debugger;

            //this.showpopup(e, titleDiv, descDiv);                   
        }
        //return true;
    },

    disableHideInfoBox: function() {
        //Only want to assign this once
        if (this._hideInfoboxFunction == null)
            this._hideInfoboxFunction = window.ero.hide;

        window.ero.hide = function(a) {
            return;
        }
    },

    enableHideInfoBox: function() {
        window.ero.hide = this._hideInfoboxFunction;
        //this._veMap.HideInfoBox(this._currentShape);
    },

    customShowInfoBox: function(shape) {
        if (!shape)
            return;

        this.disableHideInfoBox();
        this._veMap.ShowInfoBox(shape);
    },

    customHideInfoBox: function(shape) {
        if (!shape)
            return;

        this.enableHideInfoBox();
        this._veMap.HideInfoBox(shape);
    },

    mapOnLoadEvent: function(e) {
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }
        this.raisePropertyChanged('mapLoaded');
        this.doPostBack(this.createEventArgs('mapOnLoadEvent', this.createDataSet()));
    },

    mapStyleChangeEvent: function(e) {
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }

        this.doPostBack(this.createEventArgs('mapStyleChangeEvent', this.createDataSet()));
    },


    mapViewChangeEvent: function(e) {
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }

        if (this._latitude !== this._veMap.GetCenter().Latitude) {
            this._latitude = this._veMap.GetCenter().Latitude;
            this.raisePropertyChanged('latitude');
        }

        if (this._longitude !== this._veMap.GetCenter().Longitude) {
            this._longitude = this._veMap.GetCenter().Longitude;
            this.raisePropertyChanged('longitude');
        }

        if (this._zoomLevel !== this._veMap.GetZoomLevel()) {
            this._zoomLevel = this._veMap.GetZoomLevel();
            this.raisePropertyChanged('zoomLevel');
            this._clientZoomed = true;
        }

        this.doPostBack(this.createEventArgs('mapViewChangeEvent', this.createDataSet()));
    },

    mapPanStartEvent: function(e) {
        if (this._persistPopup)
            this.customHideInfoBox(this._currentShape);

        if (this._latitude !== this._veMap.GetCenter().Latitude) {
            this._latitude = this._veMap.GetCenter().Latitude;
            this.raisePropertyChanged('latitude');
        }

        if (this._longitude !== this._veMap.GetCenter().Longitude) {
            this._longitude = this._veMap.GetCenter().Longitude;
            this.raisePropertyChanged('longitude');
        }

        this.doPostBack(this.createEventArgs('mapPanStartEvent', this.createDataSet()));
    },

    mapPanEndEvent: function(e) {
        if (this._latitude !== this._veMap.GetCenter().Latitude) {
            this._latitude = this._veMap.GetCenter().Latitude;
            this.raisePropertyChanged('latitude');
        }

        if (this._longitude !== this._veMap.GetCenter().Longitude) {
            this._longitude = this._veMap.GetCenter().Longitude;
            this.raisePropertyChanged('longitude');
        }

        this.doPostBack(this.createEventArgs('mapPanEndEvent', this.createDataSet()));
    },

    mapZoomStartEvent: function(e) {
        if (this._zoomLevel !== this._veMap.GetZoomLevel()) {
            this._zoomLevel = this._veMap.GetZoomLevel();
            this.raisePropertyChanged('zoomLevel');
            this._clientZoomed = true;
        }

        this.doPostBack(this.createEventArgs('mapZoomStartEvent', this.createDataSet()));
    },

    mapZoomEndEvent: function(e) {
        if (this._zoomLevel !== this._veMap.GetZoomLevel()) {
            this._zoomLevel = this._veMap.GetZoomLevel();
            this.raisePropertyChanged('zoomLevel');
            this._clientZoomed = true;
        }

        this.doPostBack(this.createEventArgs('mapZoomEndEvent', this.createDataSet()));
    },

    mapModeInitEvent: function(e) {
        if (this._mapMode !== this._veMap.GetMapMode()) {
            this._mapMode = this._veMap.GetMapMode();
            this.raisePropertyChanged('mapMode');
        }

        this.doPostBack(this.createEventArgs('mapModeInitEvent', this.createDataSet()));
    },

    mapModeNotAvailableEvent: function(e) {
        if (this._mapMode !== this._veMap.GetMapMode()) {
            this._mapMode = this._veMap.GetMapMode();
            this.raisePropertyChanged('mapMode');
        }

        this.doPostBack(this.createEventArgs('mapModeNotAvailableEvent', this.createDataSet()));
    },

    mapObliqueEnterEvent: function(e) {
        //todo: send back birdseye orientation / scene id ? 

        //send back map style, as this may have changed
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }

        this.doPostBack(this.createEventArgs('mapObliqueEnterEvent', this.createDataSet()));
    },

    mapObliqueChangeEvent: function(e) {
        //todo: send back birdseye orientation / scene id ? 

        //send back map style, as this may have changed
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }

        this.doPostBack(this.createEventArgs('mapObliqueChangeEvent', this.createDataSet()));
    },

    mapObliqueLeaveEvent: function(e) {
        //todo: send back birdseye orientation / scene id ? 

        //send back map style, as this may have changed
        if (this._mapStyle !== this._veMap.GetMapStyle()) {
            this._mapStyle = this._veMap.GetMapStyle();
            this.raisePropertyChanged('mapStyle');
        }

        this.doPostBack(this.createEventArgs('mapObliqueLeaveEvent', this.createDataSet()));
    },

    mapResizeEvent: function(e) {
        //todo: send back map size ?           
        this.resizing = false;
        this.doPostBack(this.createEventArgs('mapResizeEvent', this.createDataSet()));
    },

    mapErrorEvent: function(e) {
        var error = this.createDataSet();

        error['error'] = e.error;

        this.doPostBack(this.createEventArgs('mapErrorEvent', error));
    },


    //creates event args to send back
    createEventArgs: function(eventName, eventArgs) {
        var event = new Object();

        event['eventName'] = eventName;
        event['eventArgs'] = eventArgs;

        return event;
    },

    //creates dataset to send back
    createDataSet: function() {

        var dataSet = new Object();

        dataSet['mapStyle'] = this._mapStyle;
        dataSet['mapMode'] = this._mapMode;
        dataSet['zoomLevel'] = this._zoomLevel;
        dataSet['latitude'] = this._latitude;
        dataSet['longitude'] = this._longitude;

        //don't know if we need to send this data back...         
        dataSet['mapFixed'] = this._mapFixed;
        dataSet['showSwitch'] = this._showSwitch;
        dataSet['tileBuffer'] = this._tileBuffer;

        dataSet['singlePinIcon'] = this._singlePinIcon; ;
        dataSet['clusteredPinIcon'] = this._clusteredPinIcon;

        dataSet['persistPopup'] = this._persistPopup;
        //debugger;

        var view = this.getView();

        if (view != null) {
            dataSet['topleftlat'] = view.TopLeftLatLong.Latitude;
            dataSet['topleftlon'] = view.TopLeftLatLong.Longitude;
            dataSet['bottomrightlat'] = view.BottomRightLatLong.Latitude;
            dataSet['bottomrightlon'] = view.BottomRightLatLong.Longitude;
        }

        if (this._currentShape != null) {
            var shapeID = this._currentShape.GetID();

            if (shapeID != null) {
                var point = this._currentShape.Point;

                if (point != null && point != "") {

                    dataSet['shapenwlat'] = point.Bounds.NW.Latitude;
                    dataSet['shapenwlon'] = point.Bounds.NW.Longitude;
                    dataSet['shapeselat'] = point.Bounds.SE.Latitude;
                    dataSet['shapeselon'] = point.Bounds.SE.Longitude;

                    dataSet['currentIndex'] = this._currentIndex;
                }
            }
        }

        //Map Properties
        if (this._veMap != null && this._veMap.GetMapStyle() != 'b' && this._veMap.GetMapStyle() != 'o') {

            dataSet['altitude'] = this._veMap.GetCenter().Altitude;
            dataSet['altitudemode'] = this._veMap.GetCenter().AltitudeMode;
        }

        //Find Results
        if (this._clientMethods != null) {
            dataSet['findresults'] = this._clientMethods.findResults;
            dataSet['places'] = this._clientMethods.vePlace;
        }
        return dataSet;
    },

    getView: function() {
        var view = this._veMap.GetMapView();

        if (view == null ||
            view.TopLeftLatLong.Latitude == null ||
            view.TopLeftLatLong.Longitude == null ||
            view.BottomRightLatLong.Latitude == null ||
            view.BottomRightLatLong.Longitude == null) {
            //debugger;        
            var be = this._veMap.GetBirdseyeScene();

            if (be != null) {
                view = be.GetBoundingRectangle();

                //however, if the orientation of the view is anything other than north,
                //then we need to jig around with the values somewhat
                switch (be.GetOrientation()) {
                    case VEOrientation.North:
                        //do nothing (we are fine as we are)
                        break;

                    case VEOrientation.South:
                        //top left is actually bottom right, and vice versa
                        var temp = view.TopLeftLatLong;
                        view.TopLeftLatLong = view.BottomRightLatLong;
                        view.BottomRightLatLong = temp;
                        break;

                    case VEOrientation.East:
                        //debugger;

                        //top left is actually top right
                        //bottom right is actually bottom left

                        var rotatedView = new VELatLongRectangle(new VELatLong(0, 0), new VELatLong(0, 0));

                        rotatedView.BottomRightLatLong.Longitude = view.TopLeftLatLong.Longitude;
                        rotatedView.BottomRightLatLong.Latitude = view.BottomRightLatLong.Latitude;

                        rotatedView.TopLeftLatLong.Longitude = view.BottomRightLatLong.Longitude;
                        rotatedView.TopLeftLatLong.Latitude = view.TopLeftLatLong.Latitude;

                        view = rotatedView;

                        break;

                    case VEOrientation.West:
                        //debugger;

                        //top left is actually bottom left
                        //bottom right is actually top right

                        var rotatedView = new VELatLongRectangle(new VELatLong(0, 0), new VELatLong(0, 0));

                        rotatedView.BottomRightLatLong.Latitude = view.TopLeftLatLong.Latitude;
                        rotatedView.BottomRightLatLong.Longitude = view.BottomRightLatLong.Longitude;

                        rotatedView.TopLeftLatLong.Latitude = view.BottomRightLatLong.Latitude;
                        rotatedView.TopLeftLatLong.Longitude = view.TopLeftLatLong.Longitude;

                        view = rotatedView;

                        break;
                }
            }
        }

        return view;
    },

    //does the post back if we have a page request manager
    doPostBack: function(eventArgs) {
        if (this.resizing) {
            resizing = false;
            return;
        }

        this.log('doPostBack: ' + eventArgs.eventName);

        if (this._prm !== null) {
            //need to get the UniqueID from the ClientID
            //TODO: Check this approach works consistently!

            var elementID = this.get_element().id;

            for (var index = 0; index < this._prm._asyncPostBackControlClientIDs.length; index++) {
                if (this._prm._asyncPostBackControlClientIDs[index] == this.get_element().id) {
                    //assume that the index of this item corresponds to the index of the uniqueID in the uniqueIDs array
                    elementID = this._prm._asyncPostBackControlIDs[index];
                }
            }

            this._prm._doPostBack(elementID, Sys.Serialization.JavaScriptSerializer.serialize(eventArgs));
        }

    },

    log: function(msg) {
        if (this._logging) {

            //            if (typeof(console) !== 'undefined' && console !== 'undefined') 
            //            {
            //                console.log(msg);
            //            }
            //            else
            //            {
            var logBox = document.getElementById('shoothill_debug_console_log');

            if (logBox != null) {
                var logEntry = document.createElement('option');

                var date = new Date();

                logEntry.innerText = date.format('HH:mm:ss.fff') + ' ' + msg;

                logBox.insertBefore(logEntry, logBox.firstChild);

                if (logBox.childNodes.length > 500)
                    logBox.removeChild(logBox.lastChild);
            }

            //            }            
        }
    },


    dispose: function() {
        this._veMap = null;

        //Add custom dispose actions here
        Shoothill.Mapping.ServerControl.Client.MappingClientControl.callBaseMethod(this, 'dispose');
    }
}


//Code to drag a polygon
//        var map = null;
//        var polygon;
//        var pointSelected=false;
//        var selectedIndex=-1;
//                
//     function GetMap()
//     {
//          map = new VEMap('myMap');
//          map.LoadMap();
//          
//          polygon = new VEShape(VEShapeType.Polygon,[new VELatLong(45,-110),new VELatLong(45,-100),new VELatLong(42,-100),new VELatLong(42,-110)]);
//          polygon.HideIcon();
//          map.AddShape(polygon);
//          
//          map.AttachEvent("onmousedown", mouseDown);
//          map.AttachEvent("onmousemove", mouseMove);
//          map.AttachEvent("onmouseup", mouseUp);
//     }
//     
//     function mouseDown(e)
//     {
//         if(e.rightMouseButton)
//         {
//             var x = e.mapX;
//             var y = e.mapY; 
//             var origin = map.PixelToLatLong(new VEPixel(x,y));
//             
//             var index = findIndex(polygon, origin, e.zoomLevel);
//             
//             if(index!=-1)
//             {
//                selectedIndex = index;
//                  pointSelected=true;   
//               }
//               
//               return true;
//         }
//     }
//     
//     function mouseMove(e)
//     {
//         if(pointSelected)
//         {
//             var x = e.mapX;
//             var y = e.mapY; 
//             var origin = map.PixelToLatLong(new VEPixel(x,y));
//                 
//             var points = polygon.GetPoints();
//             points.pop();
//             
//             points[selectedIndex]=origin;
//               polygon.SetPoints(points);
//         }
//     }
//     
//     function mouseUp(e)
//     {
//         if(pointSelected && e.rightMouseButton)
//         {
//             pointSelected=false;  
//         }
//     }
//     
//     function findIndex(shape,latlong,zoomLevel)
//     {
//         var points = shape.GetPoints();
//         points.pop();
//         
//         var offset = (20-zoomLevel)*0.05;

//         var maxLat = latlong.Latitude+offset;
//         var minLat = latlong.Latitude-offset;
//         var maxLon = latlong.Longitude+offset;
//         var minLon = latlong.Longitude-offset;
//         
//         for(var i=0; i<points.length;i++)
//         {
//             if(points[i].Latitude >= minLat && points[i].Latitude <= maxLat)
//             {
//                  if(points[i].Longitude >= minLon && points[i].Longitude <= maxLon)
//                  {
//                           return i;   
//                  }
//             }
//         }
//         
//         return -1;
//     }



Shoothill.Mapping.ServerControl.Client.MappingClientControl.registerClass('Shoothill.Mapping.ServerControl.Client.MappingClientControl', Sys.UI.Control);

if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();