/*
 * tripedia.org
 * 
 * (c) Jan Poeschko
 * 
 */

var BaseWorldMap = Class.create(Map, {
	initialize: function($super, container, options) {
		options = options || {};
		options.hash = options.hash || '';
		options.setHash = options.setHash || Prototype.emptyFunction;
		options.citiesUrl = options.citiesUrl || '';
		options.photosUrl = options.photosUrl || '';
	
		$super(container, options);
	  
	  //this.cityIcon = this.newIcon('city_small.png', 16);
	  
	  /*if (params.type)
	    this.mapType = params.type;
	  else
	    this.mapType = 'photos';*/
	  
	  this.markers = $A();
	  this.currentPhotos = $H();
	  this.currentCities = $H();
	  this.currentCountries = $H();

	  this.clickedMarker = null;
	  
	  /*this.map.setMapType(G_PHYSICAL_MAP);
	  
	  this.map.enableDoubleClickZoom();
	  this.map.enableContinuousZoom();
	  this.map.enableScrollWheelZoom();
	  
	  this.map.addControl(new GLargeMapControl());
	  this.map.addControl(new GOverviewMapControl());
	  this.map.addControl(new GScaleControl());
	  this.map.addControl(new GMapTypeControl());*/
	  
	  GEvent.addListener(this.map, 'moveend', this.refreshWorldMap.bind(this));
	  GEvent.addListener(this.map, 'zoomend', this.refreshWorldMap.bind(this));

	  //this.refreshWorldMap(true);
	  
	  GEvent.addListener(this.map, 'load', function() {
	  	this.refreshWorldMap(true);
	  }.bind(this));
	},
	
	/*setMapType: function(mapType) {
	  if (mapType != this.mapType) {
	    this.mapType = mapType;
	    
	    this.markers.each(function(marker) {
	    	this.map.removeOverlay(marker);
	    }.bind(this));

	    this.markers = $A();
	    this.currentPhotos = $H();
	    this.currentCities = $H();
	    this.currentCountries = $H();

	    this.refreshWorldMap(false);
	  }
	},*/
	
	displayPhoto: function(photo) {
	  var icon = new GIcon();
	  icon.image = this.serverAddress + photo.image.mapicon.url;
	  icon.iconSize = new GSize(photo.image.mapicon.width, photo.image.mapicon.height);
	  icon.iconAnchor = new GPoint(photo.image.mapicon.width / 2, photo.image.mapicon.height / 2);
	  icon.infoWindowAnchor = icon.iconAnchor;

	  var lat = photo.lat;
	  var lng = photo.lng;
	  if (!photo.customPos) {
	    lat += (Math.random() - 0.5) * 0.05;
	    lng += (Math.random() - 0.5) * 0.05;
	  }
	  var marker = new GMarker(new GLatLng(lat, lng), {
	  	title: photo.title,
	  	icon: icon,
	  	zIndexProcess: function() {
	  		return GOverlay.getZIndex(lat) + 1000000000;
	  	}
	  });
	  
	  marker.itemId = photo.id;
	  
	  var title = photo.title;
	  if (!title)
	  	title = "Photo";
	  
	  /*var tab = '<div class="tab">';
	  tab += '<div class="mapphoto"><a target="_top" class="image" href="' + photo.url + '"><img src="' + photo.image.portrait.url + '" width="' + photo.image.portrait.width + '" height="' + photo.image.portrait.height + '" alt="' + photo.title + '" /></a></div>';
	  tab += '<p><a target="_top" href="' + photo.url + '"><strong>' + title.escapeHTML() + '</strong></a>';
	  tab += ' <small>by <a target="_top" href="' + photo.userUrl + '">' + photo.user.escapeHTML() +
	    '</small></a></p>';
	  tab += '<p><a target="_top" href="' + photo.destination.city.url + '">' + photo.destination.city.name.escapeHTML() +
	    '</a>, ' + '<a target="_top" class="iconed" style="background-image: url(' +
	      photo.destination.country.image.icon.url + ')" href="' + photo.destination.country.url + '">' + photo.destination.country.name.escapeHTML() + '</a>';
	  tab += '<br /><a class="iconed zoom" href="javascript:zoomToPhoto(' + photo.lat + ', ' + photo.lng + ')">Zoom</a></p>';
	  tab += '</div>';*/
	  
	  var tab = $E('div', {'class': 'tab'},
	  	$E('div', {'class': 'mapphoto'},
	  		$E('a', {'target': '_top', 'class': 'image', 'href': photo.url},
	  			$E('img', {'src': photo.image.portrait.url, 'width': photo.image.portrait.width,
	  				'height': photo.image.portrait.height, 'alt': title})
	  		)
	  	),
	  	$E('p',
	  		$E('a', {'target': '_top', 'href': photo.url},
	  			$E('strong', $T(title))
	  		),
	  		$E('small',
	  			$T(' by '),
	  			$E('a', {'target': '_top', 'href': photo.userUrl}, $T(photo.user))
	  		)
	  	),
	  	$E('p',
	  		$E('a', {'target': '_top', 'href': photo.destination.city.url},
	  			$T(photo.destination.city.name)
	  		),
	  		$T(', '),
	  		$E('a', {'target': '_top', 'class': 'iconed',
	  			'style': 'background-image: url(' + photo.destination.country.image.icon.url + ')',
	  			'href': photo.destination.country.url},
	  			$T(photo.destination.country.name)
	  		),
	  		$E('br'),
	  		$E('a', {'class': 'iconed zoom'}, $T("Zoom")).observe('click', function() {
	  			this.zoomToPhoto(photo.lat, photo.lng);
	  		}.bindAsEventListener(this))
	  	)
	  );
	  
	  GEvent.addListener(marker, "click", function() {
      this.clickedMarker = marker;
      marker.openInfoWindow(tab);
	  }.bind(this));
	  
	  this.markers.push(marker);
	  this.map.addOverlay(marker);
	  
	  return marker;
	},

	displayCity: function(city) {
	  //var icon = this.cityIcon;
		
		
	
	  var icon = MapIconMaker.createFlatIcon({primaryColor: city.color, cornerColor: city.color, width: 16, height: 16});
	  
	  var marker = new GMarker(new GLatLng(city.lat, city.lng), {
	  	title: city.name,
	  	icon: icon
	  });
	  
	  marker.itemId = city.id;
	  
	  /*var tab = '<div class="tab">';
	  tab += '<a target="_top" href="' + city.url + '">' + city.name + '</a>';
	  tab += '<br /><a target="_top" class="iconed" style="background-image: url(' + city.country.image.icon.url + ')" href="' + city.country.url + '">' + city.country.name + '</a>';
	  tab += '<br /><a class="iconed zoom" href="javascript:zoomToCity(' + city.lat + ', ' + city.lng + ')">Zoom</a>';
	  tab += '</div>';*/
	  
	  var tab = $E('div', {'class': 'tab'},
	  	$E('strong', $E('a', {'target': '_top', 'href': city.url}, $T(city.name))),
	  	$E('br'),
	  	$E('a', {'target': '_top', 'class': 'iconed',
	  		'style': 'background-image: url(' + city.country.image.icon.url + ')',
	  		'href': city.country.url},
	  		$T(city.country.name)
	  	),
	  	$E('br'),
  		$E('a', {'class': 'iconed zoom'}, $T("Zoom")).observe('click', function() {
  			this.zoomToCity(city.lat, city.lng);
  		}.bindAsEventListener(this))
	  );
	  
	  GEvent.addListener(marker, "click", function() {
      this.clickedMarker = marker;
      marker.openInfoWindow(tab);
	  }.bind(this));
	  
	  this.markers.push(marker);
	  this.map.addOverlay(marker);
	  return marker;
	},

	displayCountry: function(country) {
	  var icon = new GIcon();
	  icon.image = this.serverAddress + country.image.icon.url;
	  icon.iconSize = new GSize(country.image.icon.width, country.image.icon.height);
	  icon.iconAnchor = new GPoint(8, 8);
	  icon.infoWindowAnchor = new google.maps.Point(8, 8);

	  var marker = new GMarker(new GLatLng(country.lat, country.lng), {
	  	title: country.name,
	  	icon: icon
	  });
	  
	  marker.itemId = country.id;
	  
	  /*var tab = '<div class="tab">';
	  tab += '<strong><a class="iconed" target="_top" style="background-image: url(' + country.image.icon.url + ')" href="' + country.url + '">' + country.name + '</a></strong>';
	  //tab += '<br /><a target="_top" href="' + country.url + '">Go to country\'s overview page</a>';
	  tab += '<br /><a class="iconed zoom" href="javascript:zoomToCountry(' + country.lat + ', ' + country.lng + ')">Zoom</a>';
	  tab += '</div>';*/
	  
	  var tab = $E('div', {'class': 'tab'},
	  	$E('strong', $E('a', {'class': 'iconed', 'target': '_top',
	  		'style': 'background-image: url(' + country.image.icon.url + ')',
	  		'href': country.url},
	  		$T(country.name))),
  		$E('br'),
  		$E('a', {'class': 'iconed zoom'}, $T("Zoom")).observe('click', function() {
  			this.zoomToCountry(country.lat, country.lng);
  		}.bindAsEventListener(this))
	  );
	  
	  GEvent.addListener(marker, 'click', function() {
      marker.openInfoWindow(tab);
	  });
	  
	  this.markers.push(marker);
	  this.map.addOverlay(marker);
	  
	  return marker;
	},

	updateWorldItems: function(kind, items, currentItems, displayFunc) {
	  var newItems = $H();
	  for (var i = 0; i < items.length; ++i) {
	    var id = items[i].id;
	    if (currentItems.get(id)) {
	      newItems.set(id, currentItems.get(id));
	    } else {
	      newItems.set(id, displayFunc(items[i]));
	    }
	  }
	  
	  var deletedItems = $H(currentItems);
	  newItems.each(function(pair) {
	    deletedItems.unset(pair.key);
	  });
	  if (this.clickedMarker)
	    deletedItems.unset(this.clickedMarker.itemId);  // don't delete clicked marker!
	  deletedItems.each(function(pair) {
	  	pair.value.hide();
	  }.bind(this));
	  this.markers = this.markers.without(deletedItems.values());
	  
	  currentItems.each(function(pair) {
	  	currentItems.unset(pair.key);
	  });
	  newItems.each(function(pair) {
	  	currentItems.set(pair.key, pair.value);
	  });
	},

	refreshLocation: function() {
	  var center = this.map.getCenter();
	  var zoom = this.map.getZoom();
	  var hash = //'type=' + this.mapType +
	  	'lat=' + center.lat() + '&lng=' + center.lng() + '&z=' + zoom;
	  this.options.setHash(hash);
	},

	refreshWorldMap: function(dontRefreshLocation) {
	  if (!dontRefreshLocation)
	    this.refreshLocation();

	  var mapBounds = this.map.getBounds();
	  var parameters = { zoom: this.map.getZoom() };
	  if (!mapBounds.isFullLat()) {
	    parameters.from_lat = mapBounds.getSouthWest().lat();
	    parameters.to_lat = mapBounds.getNorthEast().lat();
	  }
	  if (!mapBounds.isFullLng()) {
	    parameters.from_lng = mapBounds.getSouthWest().lng();
	    parameters.to_lng = mapBounds.getNorthEast().lng();
	  }
	  var requestUrl = this.options.itemsUrl;
	  new Ajax.Request(requestUrl, {
	    method: 'get',
	    parameters: parameters,
	    onSuccess: function(transport) {
	      var data = transport.responseText.evalJSON();
	      
	      this.updateWorldItems('countries', data.countries, this.currentCountries, this.displayCountry.bind(this));
	      this.updateWorldItems('cities', data.cities, this.currentCities, this.displayCity.bind(this));
	      this.updateWorldItems('photos', data.photos, this.currentPhotos, this.displayPhoto.bind(this));
	      this.createMarkerBorders(); //.bind(this).delay(0.5);
	  	}.bind(this)
	  });
	},
	
	zoomToPhoto: function(lat, lng) {
	  this.map.setCenter(new GLatLng(lat, lng), 12);
	},

	zoomToCity: function(lat, lng) {
	  this.map.setCenter(new GLatLng(lat, lng), 12);
	},

	zoomToCountry: function(lat, lng) {
	  this.map.setCenter(new GLatLng(lat, lng), 5);
	  this.map.closeInfoWindow();
	}
});

var WorldMap = Class.create(BaseWorldMap, {
	initialize: function($super, container, options) {
		$super(container, options);
	  
	  var params = options.hash.parseQuery();
	  if (params.lat && params.lng && params.z)
	    this.map.setCenter(new GLatLng(parseFloat(params.lat), parseFloat(params.lng)),
	      parseInt(params.z));
	  else
	    this.map.setCenter(new GLatLng(22.5, 0), 2);
		
		this.map.setMapType(G_PHYSICAL_MAP);
	  
	  this.map.enableDoubleClickZoom();
	  this.map.enableContinuousZoom();
	  this.map.enableScrollWheelZoom();
	  
	  //this.addControl(new GLargeMapControl());
	  //var extLargeMapControl = new ExtLargeMapControl();
    //this.addControl(extLargeMapControl);
		this.addControl(new ExtLargeMapControl());
	  this.addControl(new GOverviewMapControl());
	  this.addControl(new GScaleControl());
	  this.addControl(new GMapTypeControl());
	}
});

var CityMap = Class.create(BaseWorldMap, {
	initialize: function($super, container, city, options) {
		$super(container, options);
		
		this.map.setCenter(new GLatLng(city.lat, city.lng), 12);
		//this.map.setMapType(G_STREET_MAP);

		this.map.setMapType(G_NORMAL_MAP);
		
		//this.map
	  //this.addControl(new GSmallZoomControl());
		this.addControl(new ExtLargeMapControl({type: 'small'}));
	}
});

var CountryMap = Class.create(BaseWorldMap, {
	initialize: function($super, container, country, options) {
		$super(container, options);
		
		var bounds = new GLatLngBounds(new GLatLng(country.bboxSouth, country.bboxWest),
			new GLatLng(country.bboxNorth, country.bboxEast));
		
		this.map.setCenter(bounds.getCenter(), this.map.getBoundsZoomLevel(bounds));
		//this.map.setMapType(G_STREET_MAP);

		this.map.setMapType(G_PHYSICAL_MAP);
		
	  //this.addControl(new GSmallZoomControl());
		this.addControl(new ExtLargeMapControl({type: 'small'}));
	}
});