﻿// Class ResultsMap

BenefulMap.ResultsMap = Class.extend({
	init: function(mapCanvas, infoWinDiv) {
        this.mapCanvas = mapCanvas;
        this.infoWinDiv = infoWinDiv;
        
        this.mapState;
        
        this.map;
        
        this.geocoder = new GClientGeocoder();
        this.markers = [];
        
        this.loadMapListener();
	},
	getMapCanvas: function() {
	   return this.mapCanvas;
	},
	setMapCanvas: function(mapCanvas) {
	   this.mapCanvas = mapCanvas;
	},
    getMap: function() {
        return this.map;
    },
    setMap: function(newMap) {
        this.map = newMap;
    },
    getMapState: function() {
        return this.mapState;
    },
    setMapState: function(mapState) {
        this.mapState = mapState;
    },
    getInfoWinDiv: function() {
        return this.infoWinDiv;
    },
    getGeocoder: function() {
        return this.geocoder;
    },
    getMarkers: function() {
        return this.markers;
    },
    setMarkers: function(markers) {
        this.markers = markers;
    },
	loadMapListener: function() {
	   var self = this;
	   $(document).bind("map.load", function(event, mapState) {
	       self.loadMap(mapState);
	   });
	},
	loadMap: function(mapState) {
    	this.setMapState(mapState);
	    console.log(mapState);
	    gmap = new GMap2( $(this.getMapCanvas()).get(0));	    
    	var initialLocation = new GLatLng(mapState.getLatitude(), mapState.getLongitude());
    	gmap.setCenter(initialLocation,mapState.getDefaultZoom());
        gmap.addControl(new GLargeMapControl3D() );
    	gmap.clearOverlays();
        this.setMap(gmap);
        
    	$(this.getInfoWinDiv()).appendTo( gmap.getPane(G_MAP_FLOAT_PANE));
    	this.setMapState(mapState);
    	
    	this.globalMapListeners();
    	this.searchMapListener();
    	this.updateMapListener();
        this.invalidMapListener();

        if (mapState.isValid()) {
            console.log("triggering location.update, count.update");
            $(document).trigger('location.update', [mapState]);
        	$(document).trigger('count.update', [mapState]);
        }
        $(document).trigger('map.loaded', [mapState]);
	},
	globalMapListeners: function() {
	   	var self = this;
	   	$("window").resize( function() { 
    		self.getGmap().checkResize(); // Map refreshes if window resized
    	});

    	$("window").unload( function() {
    		GUnload(); // Avoid memory leaks in IE
    	});
	},
	searchMapListener: function() {
	   var self = this;
	   $(document).bind('map.search', function(event, address) {
	       self.searchMap(address);
	   });
	},
	searchMap: function(address) {
	    var self = this;
	    var geo = this.getGeocoder();
	    var mapState = this.getMapState();
	    $("#map-top-panel-contents h3").hide();
		geo.getLocations(address, function(result) {
			if (result == null || result.Status.code == 602 || result.Status.code == 500) {
                self.geocoderError();
			} else {
				console.info("valid geocoder data");
				mapState.setDefaultView(false);
				self.setMapState(mapState);
				self.validGeocode(result);
			}
		});
	},
	geocoderError: function() {
	   	console.warn("Input error in geocoder data");
		var mapState = this.getMapState();
		var map = this.getMap();
		
		mapState.inputError();
		map.setCenter(BenefulMap.Constants.CENTER_LATLNG);
		this.setMapState(mapState);
		
		$("#map-top-panel-contents h3").hide();
		$("#pagination-pane").hide();
		$("#results-sort-wrap").hide();

		$(document).trigger('results.invalid', [mapState]);
	},
	validGeocode: function(result) {
	    var mapState = this.getMapState();
	    console.log('valid geocode', mapState);
	    console.log('result: ', result);
		var loc = result.Placemark[0];
		this.getLocationFromGeocoder(loc);

	    mapState.validQuery();
		mapState.setLatitude( loc.Point.coordinates[1].toString() );
		mapState.setLongitude( loc.Point.coordinates[0].toString() );
		mapState.scrapeRadius("#radius"); // TODO search bar should supply this
		mapState.scrapeCategories("#category-filter input"); // TODO search bar should supply this
		mapState.resetPage();
		mapState.scrapeSearchField("#target-address");
		mapState.setGoButtonClicked(true);
		this.setMapState(mapState);
		this.setMapCookie(mapState);

        $(document).trigger('location.update', [mapState]);
    	$(document).trigger('count.update', [mapState]);
    	$(document).trigger('results.update', [mapState]);
	},
	getLocationFromGeocoder: function(loc) {
		var mapState = this.getMapState();
		var details = loc.AddressDetails.Country.AdministrativeArea;
		var city;
		var state;
		if (details.Locality) {
			console.info("details.Locality defined");
			city = details.Locality.LocalityName;
			state = details.AdministrativeAreaName;
			mapState.setLocation( city + ", " + state );
			} else {
				try {
					city = details.SubAdministrativeArea.Locality.LocalityName;
					state = details.AdministrativeAreaName;
					mapState.setLocation( city + ", " + state );
				}
				catch(error) {
					console.log(error);
					state = details.AdministrativeAreaName;
					mapState.setLocation( state + ", USA");
				}
			}
		
		this.setMapState(mapState);
	},
	updateMapListener: function() {
	   var self = this;
	   $(document).bind('map.update', function(event, mapState) {
	       console.log("map.update event fired");
	       self.updateMap(mapState);
	   });
	},
	updateMap: function(mapState) {	    
        $(document).trigger('infowin.close');
        mapState.scrapeSpotIds("#results-items > li:not(li.promo_callout)");
        this.setMapState(mapState);
        var self = this;

        WagWorld.Web.AjaxUtility.GetMapLocations(mapState.toJSON(), function(result) {
           console.log("map.update fired - ", mapState);
           var gmap = self.getMap();
           gmap.clearOverlays();
           if (result.value == null) {
               self.invalidData();
           } else {
               if (!mapState.isNoCookieDetected()) {
                   mapState.validQuery();
                   self.setMapState(mapState);
               }
               var spots = result.value;
               if (spots.length) {
                   self.arrangeMarkers(spots);
               } else {
                   self.noSpotsFound();
               }
           }   
           $(document).trigger('count.update', [mapState]); 
       });
	},
	invalidData: function() {
	    console.warn("Input error in ajax pro get map locations");
		this.getMapState().inputError();
		this.setMapState(mapState);
		$("#map-top-panel-contents h3").hide();
	},
	arrangeMarkers: function(spots) {
		var mapState = this.getMapState();
		var gmap = this.getMap();	
		$("#map-top-panel-contents h3").show();
		$("#results-sort-wrap").show();
		$("#pagination-pane").show();
		var bounds = new GLatLngBounds(); // create a bounds object, which we will use later to extend the viewport  
	    var markers = [];
		for (var i = 0; i < spots.length; i++) { // for each result, create a new "point" object and a marker, then extend the bounds of the map to ensure all markers are visible        
	        var point = new GLatLng(spots[i].Latitude, spots[i].Longitude);
			var markerData = {};
			var offset = mapState.getPage() -1;
			var markerLetters = [];
			if (offset == 0) {
				markerLetters = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
			} else {
				markerLetters = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
			}
			if (offset > 0) {
				if (i < 9) {
					markerData.spotNum = offset + markerLetters[i];
				} else {
					markerData.spotNum = (offset + 1) + markerLetters[i];
				}
			} else {
				markerData.spotNum = markerLetters[i];
			}	
			markerData.spotId = spots[i].BusinessId;
			markerData.spotName = spots[i].Name;
	        var marker = this.createMarker(point, markerData, mapState); //create a map marker at this point on the map   
			markers.push(marker);
			bounds.extend(point);  //extend the map bounds (viewport) so that this point is shown        
	    }
		mapState.setMarkers(markers);
		this.setMarkers(markers);
		var loc, zoom;
		if (!mapState.isDefaultView()) {
			console.log("search view");
			loc = new GLatLng(bounds.getCenter().lat(), bounds.getCenter().lng());
		    zoom = gmap.getBoundsZoomLevel(bounds);
		    if (zoom > 15) {
		        zoom = 15;
		    }
		    
		} else {
			console.log("default view");
			loc = BenefulMap.Constants.CENTER_LATLNG;
			zoom = BenefulMap.Constants.USA_ZOOM;
		}
		gmap.setCenter(loc, zoom); // After all the markers are on the map, center the map
	    
		$(".markerLabel").each(function() {
			if (parseInt($(this).text()) > 99) {
				$(this).addClass("smallMarkerFont");
				var left = $(this).css("left");
				console.log(left);
				var newLeft = parseInt(left) - 3;
				 $(this).css("left", newLeft);
			}
		});
	},
	noSpotsFound: function() {
	   	var mapState = this.getMapState();
	   	var gmap = this.getMap();
	   	var zoomLevel;
	   	
		if (mapState.isNoCookieDetected()) {
			zoomLevel = BenefulMap.Constants.USA_ZOOM;
		} else {
		    zoomLevel = BenefulMap.Constants.CITY_ZOOM;
		}
		var searchLocation = new GLatLng(mapState.getLatitude(), mapState.getLongitude());
		gmap.setCenter(searchLocation, zoomLevel);
		$("#results-sort-wrap").hide();
		$("#pagination-pane").hide();
	},
	setMapCookie: function() {
	   var mapState = this.getMapState();
	   WagWorld.Web.AjaxUtility.SetLocationCookie(mapState.getLatitude(), mapState.getLongitude(), mapState.getLocation(), function(result) {
           console.log("SetLocationCookie() - ", result);
       });
	},
	createMarker: function(point, markerData) {
	    var map = this.getMap();

    	var customIcon = new GIcon();
        customIcon.image = BenefulMap.Constants.IMG_MARKER;
    	customIcon.iconSize = new GSize(44,41);
        customIcon.iconAnchor = new GPoint(17,41);
        customIcon.infoWindowAnchor = new GPoint(0,0); 

    	opts = { 
    	    "title": markerData.spotName,
    		"icon": customIcon,
    		"clickable": true,
    		"labelClass": "markerLabel",
    		"labelText": markerData.spotNum
    	};
    	if (markerData.spotNum > 9) { // 2 digits
    		opts.labelOffset = new GSize(-7, -35); 
    	} else if (markerData.spotNum > 99) { // 3 digits
    		opts.labelOffset = new GSize(-30, -33); 
    	} else { // 1 digit
    		opts.labelOffset = new GSize(-4, -35); 
    	}

    	var marker = new LabeledMarker(point, opts);
    	marker.spotNum = markerData.spotNum;
    	marker.spotId = markerData.spotId;
    	marker.spotName = markerData.spotName;
    	map.addOverlay(marker); 
        
        this.setupMarkerListeners(marker);
    	return marker;
	},
	setupMarkerListeners: function(marker) {
	    marker.isActive = false;
	    var mapState = this.getMapState();
	    var map = this.getMap();
	    var self = this;
	    
	    GEvent.addListener(marker,'click', function() {
    		$(document).trigger('infowin.close');
    		console.log("marker clicked");
    		$(document).trigger('infowin.load', [marker, mapState, map]);
    		jQuery.each(self.markers, function() {
    		   this.setImage(BenefulMap.Constants.IMG_MARKER); 
    		});
    		marker.setImage(BenefulMap.Constants.IMG_ACTIVE_MARKER);
    		marker.isActive = true;
    	});
        
    	GEvent.addListener(marker, 'mouseover', function() {
    		if (!marker.isActive) {
    		    marker.setImage(BenefulMap.Constants.IMG_ACTIVE_MARKER);
    		}
    	});

    	GEvent.addListener(marker, 'mouseout', function() {
    		if (!marker.isActive) {
    		     marker.setImage(BenefulMap.Constants.IMG_MARKER);
    		}
    	});

    	GEvent.addListener(this.getMap(), "click", function() {
    	    jQuery.each(self.markers, function() {
    	       this.setImage(BenefulMap.Constants.IMG_MARKER);
    	       this.isActive = false;
    	    });
            $(document).trigger('infowin.close');
    	});
        
    	// these listeners are for items in the results pane
    	var resultListing = "#" + BenefulMap.Constants.Strings.RESULTS_ITEM_PREFIX + marker.spotId;

    	$(resultListing).click( function() {
    	    console.log("icon clicked");
    		$(document).trigger('infowin.close');
    		$(document).trigger('infowin.load', [marker, mapState, map]);
    	});
    	
    	$(resultListing).mouseover( function() {
    		$(this).addClass("hover");
    	});
    	
    	$(resultListing).mouseout(function() {
    		$(this).removeClass("hover");
    	});
	},
	invalidMapListener: function() {
	   var self = this;
	   var map = this.getMap();
	   $(document).bind('map.invalid', function(event, mapState) {
	       console.log("map.invalid", mapState);
	       mapState.spotIds = [];
           mapState.markers = [];
           self.setMapState(mapState);
           map.clearOverlays();
           map.setCenter(BenefulMap.Constants.CENTER_LATLNG, BenefulMap.Constants.USA_ZOOM);
	   });
	}
});	



