﻿general.namespace('SW.Markers');

(function () {

        var Markers = SW.Markers;

        // holds points and markers of one type for whole world at top zoom levels (1 to 5)
		
		/* CONSTRUCTOR
		     One MarkerWorld per marker type. Used for marker data at zoom level up to MarkerWorld.MAX_ZOOM.
		     One point per sector (either an individual marker or a point representing multiple markers).
		 */
		var MarkerWorld = Markers.MarkerWorld = function (markerType, points) {
			this.markerType = markerType;
			this.points = points;
			this.markersByZoom = {};
		};
		MarkerWorld.prototype.constructor = MarkerWorld;
				
		MarkerWorld.MIN_ZOOM = 1;
		MarkerWorld.MAX_ZOOM = 5;
		
		MarkerWorld.numMarkerWorldRequestFailuresSinceLastSuccess = 0;
		
		MarkerWorld.typesPendingRequest = {};
		
		/*
		 */
		MarkerWorld.requestMarkerWorld = function (markerType, markerGrid) {
		    
		    if (!MarkerWorld.typesPendingRequest[markerType]) {
			    YAHOO.util.Connect.asyncRequest(
                    'POST',
                    '/WebServices/DataPoints.asmx/GetZoomedOutPoints?r=' + general.rand(),
                    {
                        success: MarkerWorld.onMarkerWorldRequestSuccess,
                        failure: MarkerWorld.onMarkerWorldRequestFailure,
                        argument: {
                            markerGrid: markerGrid,
                            markerType: markerType
                        }
                    },
                    JSON.encode({dataType: markerType})  // post data
                );    
			    
			    SWMap.loadingIndicator.addLoad();
			    
			    MarkerWorld.typesPendingRequest[markerType] = true;
			    Markers.requestsPending++;
		    }
		};
		
		
		/*
		 */
		MarkerWorld.onMarkerWorldRequestSuccess = function (response) {
		    SWMap.loadingIndicator.removeLoad();
		    
		    MarkerWorld.numMarkerWorldRequestFailuresSinceLastSuccess = 0;
			
			var points = general.evalXmlResult(response.responseXML);
            
            if (points) {

			    // set up points
			    for (var i = 0; i < points.length; i++) {
				    var p = points[i];
    				
				    var point = {
					    id: p.I,
					    sectorId: p.SI,
					    lat: p.Lat,
					    lng: p.Lng,
					    name: p.N,
					    dataTypeId: p.T,
					    count: p.C
				    };
    				
				    if (point.count > 1) {
					    point.bounds = Markers.Sector.sectorIdToBounds(point.sectorId); // a sector with multiple points should display as a group marker, and so a bounds is needed to zoom in on
				    }
    				
				    points[i] = point;
			    }

			    var markerGrid = response.argument.markerGrid;
			    var markerType = response.argument.markerType;
    			
			    MarkerWorld.typesPendingRequest[markerType] = false;
			    Markers.requestsPending--;
    			
			    markerGrid.markerWorldsByType[markerType] = new MarkerWorld(markerType, points);
			    markerGrid.updateMarkerDisplay();
			}
			else {
			    MarkerWorld.onMarkerWorldRequestFailure(response);
			}
		};
		
		
		/*
		 */
		MarkerWorld.onMarkerWorldRequestFailure = function (response) {
		    SWMap.loadingIndicator.removeLoad();
		
		    var args = response.argument;
		    
		    MarkerWorld.numMarkerWorldRequestFailuresSinceLastSuccess++;
		    MarkerWorld.typesPendingRequest[args.markerType] = false;  // don't block reattempts to get this type
		    Markers.requestsPending--;
		    
		    if (MarkerWorld.numMarkerWorldRequestFailuresSinceLastSuccess <= 2) {
		        args.markerGrid.updateMarkerDisplay();
			}
			else {
			    general.reportClientError('Marker world request failure: ' + response.responseText);
			}
		};
		
		
		/**/
		MarkerWorld.prototype.getMarkersByZoom = function (zoom) {
		
			if (zoom < MarkerWorld.MIN_ZOOM || zoom > MarkerWorld.MAX_ZOOM) {
				throw "attempted to get wrong zoom from MarkerWorld";
			}
			
			if (!this.markersByZoom[zoom]) {
				
				var numLatSections = 5 * Math.pow(2, zoom - 1); // 7 at zoom lvl 1, then double for each lvl after that
				var numLngSections = numLatSections * 2; // double because there are twice as many lng degrees as lat
			
				var newMarkers = Markers.createMarkers(
					this.points,
					mapGeneral.BOUNDS_OF_WHOLE_WORLD,
					this.markerType,
					numLatSections,
					numLngSections
				);
				
				this.markersByZoom[zoom] = newMarkers;
			}	        
			return this.markersByZoom[zoom];
		};

})();