var MapControl = {};

MapControl.MODE_VIEW 	= 0
MapControl.MODE_ADD 	= 1
MapControl.MODE_TAG 	= 2;

MapControl.spotTypes	= [
	"Street Spot",
	"Skate Park",
	"Inhouse Park",
	"Skate Ramp",
	"Bowl",
	"Other"
];
MapControl.flattenObject = function(parseObj, flatObj){
	for(var param in parseObj){
		if(typeof(parseObj[param]) == "object"){
			// recurse
			MapControl.flattenObject(parseObj[param], flatObj);
		}else if(typeof(parseObj[param]) == "string" || typeof(parseObj[param]) == "number"){
			flatObj[param] = parseObj[param];
		}
	}
}
MapControl.addSpot = Class.create({
	initialize: function(startLat, startLng, startZoom, mapMode, loadUrl, infoUrl, reverseCallback, loadType, showPins, smallControls) {
		
		this.SHOW_PINS			= showPins ? showPins : 4;	// At what level to show pins
	
		// Set basic Pins
		this.loadUrl			= loadUrl; 
		this.infoUrl			= infoUrl; 
		this.mapMode			= mapMode;
		this.loadType			= loadType ? loadType : 0;
		// Types
		// All = 0
		// Videos = 1
		// Events = 2
		// Crews = 3
		// Only Spots = 4
		
		var basePin 			= new GIcon();
		/*basePin.shadow 			= "/public/images/gmap/pin_shadow.png";
		basePin.iconSize 		= new GSize(12,20);
		basePin.shadowSize 		= new GSize(19,20);
		basePin.iconAnchor 		= new GPoint(9,20);
		basePin.infoWindowAnchor= new GPoint(6,7);
		*/
		basePin.shadow 			= "/public/images/icons/pins/pin_shadow.png";
		basePin.iconSize 		= new GSize(25, 29);
		basePin.shadowSize 		= new GSize(42, 29);
		basePin.iconAnchor 		= new GPoint(13, 29);
		basePin.infoWindowAnchor= new GPoint(13, 10);
		this.redPin 			= new GIcon(basePin);    
		this.redPin.image 		= "/public/images/gmap/pin_red.png";
		
		this.pins				= new Array();
		this.pins[0] 			= new GIcon(basePin);    
		this.pins[0].image 		= "/public/images/icons/pins/pin_street.png";
		this.pins[1] 			= new GIcon(basePin);    
		this.pins[1].image 		= "/public/images/icons/pins/pin_park.png";
		this.pins[2] 			= new GIcon(basePin);    
		this.pins[2].image 		= "/public/images/icons/pins/pin_inhouse.png";
		this.pins[3] 			= new GIcon(basePin);    
		this.pins[3].image 		= "/public/images/icons/pins/pin_ramp.png";
		this.pins[4] 			= new GIcon(basePin);    
		this.pins[4].image 		= "/public/images/icons/pins/pin_bwl.png";
		this.pins[5] 			= new GIcon(basePin);    
		this.pins[5].image 		= "/public/images/icons/pins/pin_other.png";
		
		this.pins[200] 			= new GIcon(basePin);    
		this.pins[200].image 	= "/public/images/icons/pins/pin_crew.png";
		this.pins[210] 			= new GIcon(basePin);    
		this.pins[210].image 	= "/public/images/icons/pins/pin_crew.png";
		this.pins[300] 			= new GIcon(basePin);    
		this.pins[300].image 	= "/public/images/icons/pins/pin_shop.png";
		
		this.yellowPin 			= new GIcon(basePin); 
		this.yellowPin.image 	= "/public/images/icons/pins/pin_new.png";
		
		// Set Map functionality
		this.map = new GMap2($("map_canvas"));
		if(smallControls){
			this.map.addControl(new GSmallMapControl());
		}else{
			this.map.addControl(new GLargeMapControl());
		}
		this.map.addControl(new GMapTypeControl());
		this.map.setCenter(new GLatLng(startLat, startLng), startZoom);
		
		// Set Map Events
		this.allMarkers = new Array();
		this.newMarker = null;
		if(this.mapMode == MapControl.MODE_ADD){
			GEvent.bind(this.map, "click", this, function(overlay, latlng) {
				if (overlay){
					return false;
				}else if (latlng) {
					if(this.newMarker)
						this.map.removeOverlay(this.newMarker);
				
					this.newMarker = new GMarker(latlng, this.yellowPin);
					this.setCoords(latlng.lat(), latlng.lng());
					this.map.addOverlay(this.newMarker);

					this.reverseGeo.reverseGeocode(latlng);
				}
			});
			// reverse geocoder

			this.reverseGeo = new GReverseGeocoder(this);
			var reverseFunc = reverseCallback;
			GEvent.addListener(this.reverseGeo, "load", function(placemark){
				var flatPlacemark = new Object();
				MapControl.flattenObject(placemark, flatPlacemark);
				
				if(flatPlacemark.Accuracy == 6){
					var geoObject 		= new Object();		
					geoObject.country 	= flatPlacemark.CountryNameCode || "";
					geoObject.state 	= flatPlacemark.AdministrativeAreaName || "";
					geoObject.city 		= flatPlacemark.LocalityName || "";
					if(typeof(flatPlacemark.DependentLocalityName) == "undefined"){
						geoObject.street 	= flatPlacemark.ThoroughfareName || "";
					}else{
						geoObject.street 	= flatPlacemark.ThoroughfareName?(flatPlacemark.ThoroughfareName +", "+ flatPlacemark.DependentLocalityName):"";
					}
					
					reverseFunc(geoObject, true);
				
				}else{
					reverseFunc(null, false);
				}
				
			});
    		GEvent.addListener(this.reverseGeo, "error", function(){
    			reverseFunc(null, false);
    		});
    
		}
		GEvent.bind(this.map, "zoomend", this, function(oldLevel,  newLevel) {
			if(newLevel >= this.SHOW_PINS){
				// load markers
				if($('zoommore'))
					$('zoommore').hide();
				this.loadBoundedSpots();
			}else{
				// show zoom sign
				if($('zoommore'))
					$('zoommore').show();
				if($('emptyarea'))
					$('emptyarea').hide();
				this.clearSpots();
			}
		});
		GEvent.bind(this.map, "moveend", this, function() {
			if(this.map.getZoom() >= this.SHOW_PINS){
		  		this.loadBoundedSpots();
		  	}
		});
		this.map.enableDoubleClickZoom();
		this.map.enableScrollWheelZoom();
		
		if($('emptyarea'))
			$('emptyarea').hide();
		if(startZoom >= this.SHOW_PINS){
			// load markers
			if($('zoommore'))
				$('zoommore').hide();
			this.loadBoundedSpots();
		}
		/*var myEventListener2 = GEvent.bind(this.map, "dblclick", this, function(marker, latlng) {
		this.map.setCenter(latlng, newZoom);
		var newZoom = Math.min(this.map.getZoom() + 1, 17);
		});*/
	},
	createMarker: function(point, spotId, spotType) {
		// set a Spot
		var mapObj = this;
		//var marker = new GMarker(point, this.redPin);
		var marker = new GMarker(point, this.pins[spotType]);
		marker.spotId = spotId;
		GEvent.addListener(marker, "click", function() {
			// style="width:160px; height:120px;"
			marker.openInfoWindowHtml('<div style="width:280px;"><img style="margin: 44px 64px;" width="16" height="16" src="/public/images/ajax_loader.gif"></div>');
			
			mapObj.loadSpotInfo(marker, spotId);
		});
		this.map.addOverlay(marker);
		this.allMarkers.push(marker);
		return marker;
	},
	markerExists: function(spotId){
		for(var i=0; i < this.allMarkers.length; i++){
			if(this.allMarkers[i].spotId == spotId)
				return true;
		}
		return false;
	},
	setCoords: function(cLat, cLng){
		// Show current position
		//$('mapcoordholder').show();
		$('mapcoords').innerHTML = "Lat:"+String(cLat).substring(0,8)+"<br />Lng:"+String(cLng).substring(0,8)+"<br />";
		$('lat').value = cLat;
		$('lng').value = cLng;
	},
	saveSpot: function(formRef, facebookPublish){
		if($F('lat') == "" || $F('lng') == "" ){
			Dialogs.alert('You need to add a spot');
		}else if($F('spotname').length < 3){
			Dialogs.alert('The spot name must be a least 3 charachters');
		}else if($F('spotcity').length < 2){
			Dialogs.alert('You need to write a city/location');
		}else if($F('spotdesc').length < 3){
			Dialogs.alert('The spot description must be a least 3 charachters');
		}else{
			var spotName = formRef.spotname.value;
			var fbPublish = false;
			if(formRef.fb_publish && formRef.fb_publish.checked)
				fbPublish = true;
			$(formRef).mapObj = this;
			$(formRef).request({
				onSuccess: function(transport){
					if(transport.responseText){
						var response = transport.responseText.evalJSON(true);
						if(response.type = "success"){
							// reset
							$(formRef).mapObj.cancel();
							$(formRef).mapObj.refreshSpots();
						}
						Dialogs.alert(response.msg[0]);
						if(fbPublish){
							facebookPublish.call(null, spotName, response.msg[1]);
						}
					}else{
						Dialogs.alert("Something f**ked up, try again later!");
					}
				},
				onFailure: function(){ 
					Dialogs.alert('Something f**ked up, try again later!'); 
				}
			});
		}
	},
	saveCrew: function(formRef){
		if(($F('lat') == "" || $F('lng') == "") && $F('crewtype') != "5" ){
			Dialogs.alert('You need to add a location');
		}else if($F('crewname').length < 3){
			Dialogs.alert('The crew name must be a least 3 charachters');
		}else if($F('crewcity').length < 2 && $F('crewtype') != "5"){
			Dialogs.alert('You need to write a city/location');
		}else if($F('crewdesc').length < 3){
			Dialogs.alert('The crew description must be a least 3 charachters');
		}else{
			$(formRef).mapObj = this;
			$(formRef).request({
				onSuccess: function(transport){
					if(transport.responseText){
						var response = transport.responseText.evalJSON(true);
						if(response.type = "success"){
							// reset
							window.location.href = "/crew/"+ response.msg;
						}
					}else{
						Dialogs.alert("Something f**ked up, try again later!");
					}
				},
				onFailure: function(){ 
					Dialogs.alert('Something f**ked up, try again later!'); 
				}
			});
		}
	},
	cancel: function(){
		if(this.newMarker)
			this.map.removeOverlay(this.newMarker);
		this.setCoords("", "");
		$('addspots').reset();
		$('mapcoords').innerHTML = "Click to add";
	},
	setLoadType: function(loadType){
		this.loadType = loadType;
		this.clearSpots();
		if(this.map.getZoom() >= this.SHOW_PINS){
			this.loadBoundedSpots();
		}
	},
	loadBoundedSpots: function(){
		var gBounds = this.map.getBounds();
		var sw = gBounds.getSouthWest();
		var ne = gBounds.getNorthEast();
		this.loadSpots(sw.lat(), sw.lng(), ne.lat(), ne.lng());
	},
	loadSpots: function(swLat, swLng, neLat, neLng){
		// Read the data from example.xml
		var request = GXmlHttp.create();
		var mapObj = this;
		if(swLat && neLat){
			request.open("GET", this.loadUrl + "?swlat="+ swLat +"&swlng="+ swLng +"&nelat="+ neLat +"&nelng="+ neLng +"&type="+ this.loadType, true);
		}else{
			request.open("GET", this.loadUrl, true);
		}
		
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				var xmlDoc = GXml.parse(request.responseText);
				// obtain the array of markers and loop through it
				var allSpots = xmlDoc.documentElement.getElementsByTagName("marker");
				
				if($('emptyarea')){
					if(allSpots.length == 0){
						$('emptyarea').show();
					}else{
						$('emptyarea').hide();
					}
				}

				
				// Plot all spots
				for (var i = 0; i < allSpots.length; i++) {
					// obtain the attribues of each marker
					var spotId 		= parseFloat(allSpots[i].getAttribute("id"));
					if(!mapObj.markerExists(spotId)){
						var lat 		= parseFloat(allSpots[i].getAttribute("lat"));
						var lng 		= parseFloat(allSpots[i].getAttribute("lng"));
						var point 		= new GLatLng(lat,lng);
						var spotType	= allSpots[i].getAttribute("type");
						// create the marker
						var aSpot 		= mapObj.createMarker(point, spotId, spotType);//name,
					}
				}
				// put the assembled side_bar_html contents into the side_bar div
				// document.getElementById("side_bar").innerHTML = side_bar_html;
			}
		}
		request.send(null);
	},
	loadSpotInfo: function(marker, spotId){
		var mapObj = this;
		new Ajax.Request(this.infoUrl + spotId +"&mode="+this.mapMode, {
		  method:'get',
		  requestHeaders: {Accept: 'application/json'},
		  onSuccess: function(transport){
		    //var jsonObj = transport.responseText.evalJSON(true);
		    mapObj.drawSpotInfo(marker, transport.responseText);
		  }
		});
	},
	drawSpotInfo: function(marker, spotHTML){
		/*
		var image1src = false?("/public/spotimages/thumbs/" + jsonObj.spotImages[0].spotImageUrl):"/public/images/default_spotimage.jpg";
		var image2src = false?("/public/spotimages/thumbs/" + jsonObj.spotImages[0].spotImageUrl):"/public/images/default_spotimage.jpg";
		var spotLink = '<a href="/spot/'+ jsonObj.spotInfo.spotId +'">View Spot info</a>';
		if(this.mapMode == MapControl.MODE_TAG){
			spotLink = '<a href="javascript:void(0)" onclick="friendTagger.tagSpot('+ jsonObj.spotInfo.spotId +');return false">Tag this spot!</a>';
		}
		//width:160px; height:120px;
		marker.openInfoWindowHtml(
				'<div class="MapInfoWin">'+
				'<div class="MapInfoImg"><img src="'+ image1src +'" width="75" height="50"/><br />'+
				'<img src="'+ image2src +'" width="75" height="50"/></div>'+
				'<div class="MapInfoText"><b>'+ jsonObj.spotInfo.spotInfoName + '</b>, '+ jsonObj.spotInfo.spotInfoCity + 
				'<br />('+ MapControl.spotTypes[jsonObj.spotInfo.spotType] + ')'+
				'<br /><br />'+ jsonObj.spotInfo.spotInfoDescription+
				'<br><div class="MapInfoLink">'+ spotLink +
				'</div></div></div>');
		*/
		marker.openInfoWindowHtml(spotHTML);
	},
	clearSpots: function(){
		for(var i=0; i < this.allMarkers.length; i++){
			this.map.removeOverlay(this.allMarkers[i]);
		}
		this.allMarkers = new Array();
	},
	refreshSpots: function(){
		this.clearSpots();
		this.loadBoundedSpots();
	},
	gotoSpot: function(spotUrl){
		var cleanUrl = window.location.href.split("#")[0];
		var stateUrl = cleanUrl + "#"+ this.map.getCenter().lat() +"_"+ this.map.getCenter().lng() +"_"+ this.map.getZoom();
		window.location.href = stateUrl;
		setTimeout('window.location.href = "'+ spotUrl +'"', 100);
	},
	gotoCrew: function(crewId, crewName){
		var cleanUrl = window.location.href.split("#")[0];
		var stateUrl = cleanUrl + "#"+ this.map.getCenter().lat() +"_"+ this.map.getCenter().lng() +"_"+ this.map.getZoom();
		window.location.href = stateUrl;
		if(crewName == ""){
			setTimeout('window.location.href = "/crew/'+ crewId +'"', 100);
		}else{
			setTimeout('window.location.href = "/'+ crewName +'"', 100);
		}
	},
	placeMap: function(lat, lng){
		var point = new GLatLng(lat, lng);
        this.map.setCenter(point, 15);
	},
	findAddress: function(address, resultDiv){
		var geo;
    	var reasons=[];
    	// ====== Create a Client Geocoder ======
      	geo = new GClientGeocoder(); 
      	
      	
      	
		// ====== Array for decoding the failure codes ======
		reasons[G_GEO_SUCCESS]            = "Success";
		reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
		reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
		reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
		reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
		reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
		reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be successfully processed.";
      	
      	var thisObj = this;
      	
		geo.getLocations(address, function (result){
            //thisObj.map.clearOverlays(); 
			if (result.Status.code == G_GEO_SUCCESS) {
              // ===== If there was more than one result, "ask did you mean" on them all =====
              if (result.Placemark.length > 1) { 
                
                // Loop through the results
                var resultStr = "";
                for (var i=0; i<result.Placemark.length; i++) {
                  var p = result.Placemark[i].Point.coordinates;
                  resultStr += "<br><a class='menuLink' href='javascript:mapApp.placeMap(" +p[1]+","+p[0]+")'>"+ result.Placemark[i].address+"</a>";
                }
                $(resultDiv).update("<span class='infoText'>Did you mean:</span>" + resultStr);
              }
              // ===== If there was a single marker =====
              else {
                $(resultDiv).update("");
                var p = result.Placemark[0].Point.coordinates;
        		thisObj.placeMap(p[1],p[0]);
        		//thisObj.loadBoundedSpots();
              }
            }
            // ====== Decode the error status ======
            else {
              var reason="Code "+result.Status.code;
              if (reasons[result.Status.code]) {
                reason = reasons[result.Status.code]
              } 
              Dialogs.alert('Could not find "'+address+ '"<br /><br /> ' + reason);
            }
          }
        );
	},
	searchAddress: function(){
		if($F('findAddress') == "" || $F('findAddress') == "Road 123, Town, Country"){
			Dialogs.alert("Address is empty");
			$('findAddress').select();
		}else{
			mapApp.findAddress($F('findAddress'), 'addresses');
		}
	},
	addressMark: function(){
		if($F('findAddress') == "Road 123, Town, Country"){
			$('findAddress').value = "";
		}else{
			$('findAddress').select();
		}
	},
	addressBlur: function(){
		if($F('findAddress') == ""){
			$('findAddress').value = "Road 123, Town, Country";
		}
	}
});