var BASE_URI = "/";
var IMAGES_URI = "images/";

var Map = Class.create({

	marker: null,
	
	placeHash: {},
	initializing: true,
	author: null,
	page: 1, 
	markerBounds: null,
	initialFlickrID: null,
	sortMode: "interestingness",

	initialize: function(app, map) {
	
		this.app = app;

		// create and setup a new google map 
		this.gMap = new GMap2(map);
		
		this.initTags();
		this.gMap.enableDoubleClickZoom();
	
		this.gMap.enableScrollWheelZoom();
		this.gMap.addMapType(G_PHYSICAL_MAP);
		this.gMap.addControl(new GLargeMapControl3D(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,40)));
		this.gMap.addControl(new GMapTypeControl());
		
		// adsense
		var publisher_id = "ca-pub-6410824932406524"; // Replace 1234123412341234 with your Google AdSense client id.
		var adPos = new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(7, 20)); // Set the anchor position and GSize offset to your desired values.

adsManagerOptions = {
maxAdsOnMap : 2,
style: 'adunit',
channel: '0934123344', // This field is optional - replace 12345678 with a channel number that you created for Google AdSense tracking
position: adPos
};

		adsManager = new GAdsManager(this.gMap, publisher_id, adsManagerOptions);
		adsManager.enable();
		
		// move some DOM elements into gmap area
		this.gMap.getPane(G_MAP_MARKER_PANE).appendChild($("flickrpreview"));
		this.gMap.getPane(G_MAP_FLOAT_PANE).appendChild($("arrow"));
		
		$("photosNotFound").hide();

		var flickrID = document.location.hash.substr(1).match(/flickr:(\d*)/);
		
		if (flickrID){
			this.findPhoto(flickrID[1]);
		} else {
			this.gMap.setCenter(new GLatLng(0,0),2);
			this.gMap.setMapType(G_SATELLITE_MAP);
			this.checkHistory(true);
			this.initSearch();
			this.initHistory();
		}
		
		this.app.draw();																		
		this.initalizing = false;
	},
	
	bbox: function(){
		
		var minLng, maxLng, minLat, maxLat;
		
		var nw = this.gMap.fromContainerPixelToLatLng(new GPoint(400,75));
		var b = this.gMap.getBounds();
		
		var sw = b.getSouthWest();
		var ne = b.getNorthEast();
		
		if (b.isFullLng()){
			minLng = -179;
			maxLng =  179;
		} else {
			minLng = nw.lng();
			maxLng = ne.lng();
			if (maxLng < minLng) {
				if (Math.abs(minLng) < Math.abs(maxLng)){
					maxLng = 179;
				} else {
					minLng = -179;
				}
			}			
		}
		
		if (b.isFullLat()){
			minLat = -89;
			maxLat =  89;
		} else {
			minLat = sw.lat();
			maxLat = nw.lat();
		}

		return minLng + "," + minLat + "," +  maxLng + "," +  maxLat;		

	},
	
	reloadPoints: function(){	
		clearInterval(this.changeInterval);
		var options = {
			parameters: {
				method:				"flickr.photos.search",
				api_key:			"234b5465c2e189f88bc08fb92ad9cd1a",
				src:				"geo-tagging.de",
				sort:				this.sortMode == "interestingness" ? "interestingness-desc" : "date-posted-desc",
				min_upload_date:	1,
				extras:				"tags, owner_name, icon_server, geo, license, date_taken",
				per_page:			50,
				page:				this.page,
				accuracy:			1,
				bbox:				this.bbox(),
				format:				"json"
			},
			callbackName: "jsoncallback",
			onSuccess: this.drawSpotMarkers.bind(this)
		};
		
		if (this.tags && this.tags.selectedTag) {
			options.parameters.tags = encodeURIComponent(this.tags.selectedTag);
		}
		
		if (this.author){
			options.parameters.user_id = this.author.nsid;
		}
		
		if (this.photoset){
			options.parameters.photoset_id = this.photoset;
			options.parameters.method = "flickr.photosets.getPhotos";

		}
		
		new Ajax.ScriptRequest("http://api.flickr.com/services/rest/", options);
	},
	
	setSortMode: function(mode){
		
		if (mode == "date"){
		
			this.sortMode = "interestingness";
			
			$("sort_mode_d").addClassName("selected");
			$("sort_mode_i").removeClassName("selected");
			$("sort_mode_i").blur();
			

		} else {
			
			this.sortMode = "date";

			$("sort_mode_d").removeClassName("selected");
			$("sort_mode_i").addClassName("selected");
			$("sort_mode_d").blur();
		}
		
		this.sortMode = mode;

	},
	
	findPhoto: function(id){
		
		var options = {
		
			parameters: {
				method:				"flickr.photos.getInfo",
				api_key:			"234b5465c2e189f88bc08fb92ad9cd1a",
				src:				"geo-tagging.de",
				photo_id: 			id,
				format:				"json"
			},
							
			callbackName: "jsoncallback",
			
			onSuccess: (function(response){
				
				if (response.stat == "ok"){
									
					var photo = response.photo;	
					
					photo._tags = "";
					
					photo.tags.tag.each(function(t){
						photo._tags += t.text + " ";

					});
					
					var lng, lat, accuracy;
					
					if (!photo.location){
						
						photo.location = {

						
							longitude: Number(photo.tags.tag.find(function(tag){
								return tag.raw.match(/geo:lon=/);
							}).raw.match(/geo:lon=(.*)/)[1]),
							
							latitude: Number(photo.tags.tag.find(function(tag){
								return tag.raw.match(/geo:lat=/);
							}).raw.match(/geo:lat=(.*)/)[1]),
							
							accuracy: 15
						};

						Logger.log(photo);
					}
				
					this.gMap.setCenter(new GLatLng(photo.location.latitude, photo.location.longitude), Number(photo.location.accuracy)+1);
					this.gMap.setMapType(G_SATELLITE_MAP);
					this.placeEntrancePhoto(photo);
					
					this.initSearch();
					this.initHistory();												
				}
				
			}).bind(this),
			
			evalResponse: true
		};
		
		new Ajax.ScriptRequest("http://api.flickr.com/services/rest/", options);
	},
	
	placeEntrancePhoto: function(photo){
		
		if (photo){
			this.entrancePhoto = photo;	
		} else {
			photo = this.entrancePhoto;

		}
				
		var latLon = new GLatLng(photo.location.latitude, photo.location.longitude);
	
		new Map.FlickrImage(
			this.gMap, 
			latLon, {
				data:photo,
				handleClick:(function(){
					this.app.preview.show(photo);
				}).bind(this),
				allwaysHighlighted: true
			}
		);
		
		this.initialFlickrID = photo.id; 
	},
	
	initSearch: function(e){
		
		var zoomChanged = (function(e){
			this.changed();	
			this.app.createForm.getElement("zoom").value = this.gMap.getZoom(); 
			
		}).bind(this);

		GEvent.addListener(this.gMap, 'zoom', zoomChanged);
		GEvent.addListener(this.gMap, 'click', this.click.bind(this));
		GEvent.addListener(this.gMap, 'moveend', this.changed.bind(this));
		
		$("searchGlobal").observe("click", (function(e){
			this.gMap.setZoom(2);
			Event.stop(e);
		}).bind(this));	
	},
	
	initHistory: function(){
		
		this.historyInterval = setInterval((function(){ 
			this.checkHistory(); 
		}).bind(this), 200);
	},

	changed: function(noDelay){
		
		if (!this.app.waitForUser){
			
			var newBounds = this.gMap.getBounds(); 
			var newTag = this.tags.selectedTag;
			
			var boundsChanged = !this.lastBounds || this.lastBounds.toString() != newBounds.toString();
			var tagChanged = this.lastTag || this.lastTag != newTag;
			
			if (boundsChanged) {
				this.page = 0;
				this.lastBounds = newBounds;
			}			
	
			if (tagChanged) {
				this.page = 0;
				this.lastTag = newTag;
				$("tagsTitle").update(!newTag ? "All Tags" : "Tag: " + newTag);
			}
					
			if (noDelay || boundsChanged || tagChanged) {
				if (this.changeInterval) {
					clearInterval(this.changeInterval);
				}
				this.changeInterval = setInterval(this.reloadPoints.bind(this), 1400);
			} 
			
			this.composeHistoryLink();
		}
	},
	
	checkHistory: function(init){
		
		var tag, place, geo, waitForUser;
		var newAnchor = document.location.hash.substr(1);
		var newPage = 1;

		if (init || newAnchor != this.oldAnchor) {
			this.oldAnchor = newAnchor;
			var parts = newAnchor.split("/");
			parts.each((function(i){
				var pair = i.split(":");
				if (pair.length == 2){
					switch (pair[0]) {
						case "tag":
							tag = unescape(pair[1]);
							this.tags.selectedTag = tag;
							break;
						case "geo":
							geo = pair[1].split(",");
							this.gMap.setCenter(new GLatLng(Number(geo[0]), Number(geo[1])));
							this.gMap.setZoom(Number(geo[2]));
							
							if (typeof geo[3] != "undefined"){

								switch (geo[3]){
									case "k": this.gMap.setMapType(G_SATELLITE_MAP); break;
									case "h": this.gMap.setMapType(G_HYBRID_MAP); break;
									case "m": this.gMap.setMapType(G_NORMAL_MAP); break;
								}
							}	
							break;	
							
						case "user":
							var newName = decodeURIComponent(pair[1]);
							if (newName.indexOf("flickr.") === 0) {
								newName = newName.substring(7);

							}
								
							if (!this.author || newName != this.author.username._content) {
								this.app.waitForUser = true;
								this.app.findPeople(newName, true);
							}
							break;
							
						case "sort": 
							this.setSortMode(pair[1]);
							break;
							
						case "photoset":
							this.photoset = pair[1];
							Logger.log("Photoset: " + this.photoset);							
							break;
							
						case "page": 
							newPage = pair[1];
					}
				}
				
			}).bind(this));
			
			this.page = newPage;
			this.changed(true);	
		}		
	},
	
	composeHistoryLink: function() {
				
		var anchor = "#/";
		var share = "";
		var shareCustom = "share/#/";
		var title = "geo-tagging.de";

		if (this.author) {
						
			anchor += "user:" + this.author.username._content + "/";
			title += " / " + this.author.username._content;
			share += "user:" + this.author.id + "/";
			shareCustom += "user:" +this.author.username._content + "/";
			
			$("people_showall").show();
			$("people_found").show();
			$("people_find").hide();
			
		} else {
			
			$("people_showall").hide();
			$("people_found").hide();
			$("people_find").show();
		}
		
		var tag = this.tags.selectedTag;
		
		if (tag){
			anchor += "tag:" + tag + "/";
			share += "tag:" + tag + "/";
			shareCustom += "tag:" + tag + "/";
			title += " - Tag: " + tag;
		}
					
		var center = this.gMap.getCenter();
		var bounds = "bbox:" + this.bbox() + "/";
		
		share += bounds;
		shareCustom += bounds;
		
		var lat = center.lat().toFixed(6);
		var lng = center.lng().toFixed(6);
		
		var mapType = this.gMap.getCurrentMapType().getUrlArg();
		
		anchor += "geo:" + lat + "," + lng + "," + this.gMap.getZoom() + "," + mapType + "/";

		if (this.page && parseInt(this.page, 10) > 1 ){
			anchor += "page:" + this.page + "/";
		}
		
		if (this.sortMode == "date"){
			anchor +="sort:date/";

		}
		
		document.location.hash = anchor;
		document.title = title + " - Geotagging | Geocoding | Geokodierung | Flickr Geo Bilder | Fotos | Lokalisieren | Karte";
		
		$("share-params").innerHTML = share;
		$("share-link").href = shareCustom;
	},

	click: function(a, b){
		try  {
			var centerPos = b;
			var tags = "http://www.geo-tagging.de/#/geo:" + centerPos.lat().toFixed(6) + "," + centerPos.lng().toFixed(6)+","+this.gMap.getZoom()+",k/"; 
			$("geotags").update(tags);
		} catch(e){}
	},
	
	initTags: function(){
		this.tags = new TagCloud("tags", this);
		this.tags.addListener("onSelect", this.changed.bind(this));	
	},
	
	drawSpotMarkers: function(response){
		
		if (response.stat == "ok"){
			
			try {
				this.gMap.clearOverlays();
				this.tags.reset();	
				var t1 = new Date();
				$("photolist").update("");
				this.imageList = [];
				var li, oldName;
				this.markerBounds = new GLatLngBounds();				
				var info = response.photos || response.photoset;
				$("photos_count").update(info.total + " photos");
				var total_pages = info.pages <= 20 ? info.pages : "20+";
				this.page = parseInt(info.page, 10);
				
				$("page_number").update("Page " + info.page + " / " + total_pages);

				if (info.page > 1) {
					$("page_back").href = "#page:" + (parseInt(info.page, 10) -1);
				} else {
					$("page_back").href = document.location.href;

				}
				
				if (info.page < info.pages) {
					$("page_next").href = "#page:" + (parseInt(info.page, 10) +1);
				} else {
					$("page_next").href = document.location.href;
				}

				if (info.total > 0) {
										

					var photos = info.photo;
					
					if (typeof photos.length == "undefined") {
						photos = [photos];

					}
					try {
						var initialFlickrIDisDisplayed = false;

							
						$A(photos).each((function(photo) {
							
							var highlight = false;


							if (this.initialFlickrID == photo.id) {
								highlight = true;
								initialFlickrIDisDisplayed = true;
							}
															
							var latLon = new GLatLng(photo.latitude, photo.longitude);
		
							var fp= new Map.FlickrImage(
								this.gMap, 
								latLon, {
									data:photo,
									handleClick:(function(){
										this.app.preview.show(photo);
									}).bind(this),
									allwaysHighlighted: highlight
								}
							);
							
							this.markerBounds.extend(latLon);
													
							var ai = Element.create("a", {
								href: "http://www.flickr.com/photo.gne?id=" + photo.id,
								target:"_blank", 
								title: unescape(photo.title)
							});	
							
							fp.registerTarget(ai);
							
							var img  = Element.create("img", {
								src: "http://static.flickr.com/" + photo.server + "/" + photo.id + "_" + photo.secret + "_s.jpg",
								title: unescape(photo.title)
							});
							
							ai.appendChild(img);
							$("photolist").appendChild(ai);
							this.imageList.push(ai);		
							
							if (photo.tags && photo.tags) {
								this.tags.addTag(photo.tags, {point: photo, marker: fp, image:ai, link:li});
							}												
							
							Event.observe(ai, "click", (function(e){
								this.app.preview.show(photo);
								Event.stop(e);		
							}).bind(this), true);																				
							
						}).bind(this));
						
						if (this.initialFlickrID && !initialFlickrIDisDisplayed){
							
							this.placeEntrancePhoto();				
						}
					} catch(e){
						Logger.error(e);

					}
						
					$("photosNotFound").hide();
					$("photosFound").show();
										
					this.tags.render();		
								
				} else {
		
					var i = document.getElementsByTagName("iframe")[0]; 
					i.src = i.src;
		
					$("photosNotFound").show();
					$("tags_showall").show();
					$("photosFound").hide();		
				
					$("tags").update("");
				}
					
				var pos = Position.cumulativeOffset($("photolist"))[1];	
				app.draw();
			} catch (e) {
				Logger.error(e);

			}
		} else {
			alert(response.err.msg);

		}
		this.app.draw();
	}
});
