// ClusterMap.js
// A GoogleMaps control that can cluster markers.
// Requires jQuery v.1.1


var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}


var map = null;
var SKIINFO_ICON = new GIcon(G_DEFAULT_ICON, '/gifs/gmapicons/skiinfo.png');

if(!window.param) var param = {};

function SkiinfoMap() {
	this.gmapFeedURL = param.hostName + "/snowreport/gmap_feed.jsp";
	this.kmlURL = param.tourJson;
	this.version = "1.0";
	this.defaultMapType = G_PHYSICAL_MAP;
	this.sb = null; // sidebar
	this.vp = null; // viewport
	this.countries = {
		/* "AD", "AT", "BG", "CA", "CH", "CZ", "DE", "ES", "FR","IT", "NO", "PL", "SE", "SK", "US" */
		BLSTART:{ lat: 48.8, lng: 11.0, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/at.png'},
		SMSTART:{ lat: 48.8, lng: 11.0, zoom: 5,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/at.png'},
		AT:		{ lat: 47.34687159, lng: 14.216308, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/at.png'},
		AD:		{ lat: 42.55813826, lng: 1.5435791, zoom: 10, flag: 'http://cache.skiinfo.com/gifs/9/flags/png/ad.png'},
		BG:		{ lat: 42.56117285, lng: 25.004882, zoom: 7,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/bg.png'},
		CA:		{ lat: 52.44261787, lng:-121.55273, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/ca.png'},
		CH:		{ lat: 46.78501604, lng: 8.4594726, zoom: 7,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/ch.png'},
		CZ:		{ lat: 49.90171121, lng: 15.490722, zoom: 7,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/cz.png'},
		DE:		{ lat: 51.04139389, lng: 10.458984, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/de.png'},
		ES:		{ lat: 41.17865397, lng: -3.603515, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/es.png'},
		FR:		{ lat: 46.21926103, lng: 2.4609375, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/fr.png'},
		IT:		{ lat: 44.77793589, lng: 10.228271, zoom: 7,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/it.png'},
		NO:		{ lat: 61.31775026, lng: 9.4262695, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/no.png'},
		PL:		{ lat: 51.54975101, lng: 19.028320, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/pl.png'},
		SE:		{ lat: 62.85514553, lng: 17.006835, zoom: 5,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/se.png'},
		SK:		{ lat: 48.74170087, lng: 19.478759, zoom: 6,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/sk.png'},
		US:		{ lat: 43.26120612, lng:-114.74121, zoom: 5,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/us.png'},
		LI:		{ lat: 47.15423705, lng:9.52102661, zoom: 10,  flag: 'http://cache.skiinfo.com/gifs/9/flags/png/li.png'}
	};
	this.controls = {};

	this.TYPE_TOUR = 'tour';
	this.TYPE_ACTIVITY = 'activity';

	// loads Google Map, adding options and loading data
};

SkiinfoMap.prototype.initialize = function() {
	if (GBrowserIsCompatible && GMap2 && GBrowserIsCompatible()) {
		jQuery('body').unload(GUnload); // add unload event handler

		var mapTypesControl = new GHierarchicalMapTypeControl();
		mapTypesControl.clearRelationships();

		var opts = {
			mapTypes: [G_NORMAL_MAP, G_HYBRID_MAP, G_PHYSICAL_MAP]
		};

		var mapId = "gmap";
		map = new GMap2(document.getElementById(mapId), opts);

		// Add event listener for map type changes - to display labels on seNorge maps
		GEvent.addListener(map, "maptypechanged", mapTypeChanged);
		map.setMapType(this.defaultMapType);

		this.setInitialCenterPoint();

		if( !param.smallMap ) {
			map.addControl(new GLargeMapControl());
			map.addControl(mapTypesControl, new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(15, 7)));
		} else {
			map.addControl( new GSmallZoomControl() );
		}

		map.enableDoubleClickZoom();
		map.enableContinuousZoom();
	}

	function mapTypeChanged() {
		var mapType = this.getCurrentMapType().getName();
	}


	function getDateStr() {
		var now = new Date();
		return now.getFullYear()+"-"+(now.getMonth()+1)+"-"+now.getDate();
	}
};

SkiinfoMap.prototype.updateAll = function() {
	this.vp.update();
	if( this.sb != null ) { this.sb.handleViewPortUpdate();	}
};

SkiinfoMap.prototype.handleMoveEnd = function () {
	if( this.vp.needUpdate() ) {
		this.updateAll();
	}
};
SkiinfoMap.prototype.handleZoomEnd = function () {
	if( this.vp.needUpdate() ) {
		this.updateAll();
	}
};
SkiinfoMap.prototype.handleClick = function( overlay, latlng ) {
	if( overlay != null ) { // && overlay instanceof GInfoWindow
		return;
	}
	this.vp.click( overlay, latlng );
};


SkiinfoMap.prototype.addViewport = function() {

	this.vp = new Viewport( map );

	if( !param.smallMap ) {
		// trigger viewportupdate on filter change
		$j( "input:checkbox[name^='gMapFilter']" ).bind( 'click', {skiinfoMap:this}, function(event) { event.data.skiinfoMap.updateAll(); } )

		this.sb = new SideBar( map );
		this.sb.setViewPort( this.vp );
		this.vp.setSideBar( this.sb );
	}


	this.updateAll();

	this.fireEvent("ViewportInitialized", [ this.vp ] );
};

SkiinfoMap.prototype.addListener = function( event, fn, context ) {
	if( !this.events ) {
		this.events = {};
	}
	if( !this.events.event ) {
		this.events[event] = [];
	}

	fn2 = function() {
		fn.apply( context, arguments );
	}

	this.events[event].push( fn2 );
};

SkiinfoMap.prototype.fireEvent = function( event, args ) {
	if( !this.events ) { return; }
	if( !this.events[event] ) { return; }
	for( var i = 0; i < this.events[event].length; i++ ) {
		this.events[event][i].apply( this, args );
	}
};

// Check for countryCode parameter and zoom to country if specified
// If not, zoom to default (Europe)
SkiinfoMap.prototype.setInitialCenterPoint = function () {
	// centerpoint in the middle of europe.
	var centerPoint = new GLatLng( this.countries['DE'].lat, this.countries['DE'].lng );
	var zoomLevel = 4;
	
	// now, try to find out if we can zoom in and pan arround

	if( param.tourId ) {
		jQuery.ajax( {
				dataType: 'json',
				url: this.makeKMLURL( param.tourId ),
				success: this.createTourFromJSON.bind( this ),
				error: this.addViewport.bind( this )
				} );

	} else if( param.destinationId ) {
		jQuery.getJSON(
				this.gmapFeedURL + "?callback=?",
				{ "postdata":
					jQuery.toJSON({ 	requests: [ {
						"partner": "Summer",
						"activityType": "A",
						"offset": 0,
						"limit": 1,
						"firstElementType": this.TYPE_ACTIVITY,
						"firstElementId": param.destinationId
					} ] })
				},
				this.focusDestination.bind( this )
				);
	} else if( param.regionId ) {

		if( param.admregion ) {
			var postData = { requests: [ {
			  "partner": "Summer",
			  "activityType": "A",
			  "summaryWhen": 1,
			  "parentOregion": param.regionId
			} ] };
		}
		else {
			var postData = { requests: [ {
			  "partner": "Summer",
			  "activityType": "A",
			  "summaryWhen": 1,
			  "parentRegion": param.regionId
			} ] };
		}
		
		jQuery.getJSON(
				this.gmapFeedURL + "?callback=?",
				{ "postdata": jQuery.toJSON( postData ) },
				this.focusDestination.bind( this )
				);
	} else {
		var country;
		if( param.countryCode ) {
			country = this.countries[param.countryCode];
		} else {
			if( param.smallMap ) {
				country = this.countries["SMSTART"];
			} else {
				country = this.countries["BLSTART"];
			}
		}

		if(country.lat && country.lng && country.zoom) {
			centerPoint = new GLatLng(country.lat, country.lng);
			zoomLevel = country.zoom;
		}
		map.setCenter(centerPoint, zoomLevel);
		this.addViewport();
	}	
};


//get currently applied filters
SkiinfoMap.prototype.getFilters = function() {
	var filters = {
		filterViaferrata: true,
		filterBike: true,
		filterHiking: true,
		filterSkitour: false,
		filterKlettersteige: false,
		filterKletterhallen: true,
		filterBikeparks: true,
		filterThermen: true,
		filterSonstige: true
	};
	if( !param.smallMap ) {
		filters.filterViaferrata = $j("#gMapFilterToursClimb").attr("checked");
		filters.filterBike = $j("#gMapFilterToursBike").attr("checked");
		filters.filterHiking = $j("#gMapFilterToursTrekk").attr("checked");
		//filters.filterSkitour = $j("#gMapFilterTours").attr("checked");
		filters.filterKlettersteige = $j("#gMapFilterToursClimb").attr("checked");
		filters.filterKletterhallen = $j("#gMapFilterKletterhallen").attr("checked");
		filters.filterBikeparks = $j("#gMapFilterBikeparks").attr("checked");
		filters.filterThermen = $j("#gMapFilterThermen").attr("checked");
		filters.filterSonstige = $j("#gMapFilterSonstige").attr("checked");
	}
	return filters;
}

SkiinfoMap.prototype.filterTours = function() {
	var filters = this.getFilters();
	return ( filters.filterViaferrata || filters.filterBike || filters.filterHiking || filters.filterSkitour );
}

SkiinfoMap.prototype.filterActivities = function() {
	var filters = this.getFilters();
	return ( filters.filterKlettersteige || filters.filterKletterhallen || filters.filterBikeparks || filters.filterThermen || filters.filterSonstige );
}


SkiinfoMap.prototype.setScreen = function( displayRect ) {
	var center = displayRect.getCenter();
	var zoom = map.getBoundsZoomLevel( displayRect ); 
	map.setCenter( center );
	map.setZoom( zoom );
};

SkiinfoMap.prototype.focusDestination = function( reply ) {
	var dests = [];
	for( var i = 0; i < reply.length; i++ ) {
		dests = dests.concat( reply[i].result );
	}

	if( dests.length == 0 ) { return; }
	if( dests.length == 1 ) {
		var displayRect = null;
		var envSize = { x: 0.1, y: 0.1 };		
		if( dests[0].bounds && dests[0].bounds.northEast && dests[0].bounds.southWest ) {
			displayRect = new GLatLngBounds(
				new GLatLng( dests[0].bounds.southWest.lat - envSize.y, dests[0].bounds.southWest.lng - envSize.x ),
				new GLatLng( dests[0].bounds.northEast.lat + envSize.y, dests[0].bounds.northEast.lng + envSize.x )
			);
		}
		else {	
			displayRect = new GLatLngBounds(
				new GLatLng( dests[0].y - envSize.y, dests[0].x - envSize.x),
				new GLatLng( dests[0].y + envSize.y, dests[0].x + envSize.x)
			);
		}
		this.setScreen( displayRect );
	} else {
		displayRect = this.getBoundingBoxFrom( dests );
		this.setScreen( displayRect );
	}

	this.addViewport();
};


SkiinfoMap.prototype.createTourFromJSON = function( response, status ) {
	var tour = new Tour();
	for( var i = 0; i < response.length; i++ ) {
		x = response[i][0];
		y = response[i][1];
		tour.addPoint( x, y );
	}
	this.setScreen( tour.getBounds() );
	this.addViewport();
	this.vp.addTour( tour );
};

SkiinfoMap.prototype.makeKMLURL = function( tourId ) {
	url = this.kmlURL + tourId + ".json";
	return url;
};

SkiinfoMap.prototype.getBoundingBoxFrom = function( dests ) {
	if( dests.length < 2 ) {
		return null;
	}

	margin = 0.08;

	minX = Number.POSITIVE_INFINITY;
	minY = Number.POSITIVE_INFINITY;
	maxX = Number.NEGATIVE_INFINITY;
	maxY = Number.NEGATIVE_INFINITY;

	for( var i = 0; i < dests.length; i++ ) {
		if( dests[i].x - margin < minX ) {
			minX = dests[i].x - margin;
		}
		if( dests[i].y - margin < minY ) {
			minY = dests[i].y - margin;
		}
		if( dests[i].x + margin > maxX ) {
			maxX = dests[i].x + margin;
		}
		if( dests[i].y + margin > maxY ) {
			maxY = dests[i].y + margin;
		}
	}

	return new GLatLngBounds(
			new GLatLng( minY, minX ),
			new GLatLng( maxY, maxX ) );
};

var skiinfoMap = null
jQuery(document).ready(function() {

	// change checkboxes to ImageCheckBoxes
	var checkImgChecked = 'http://www.bergleben.de/img/checkedCheckBox_2010.png';
	var checkImgUnChecked = 'http://www.bergleben.de/img/uncheckedCheckBox_2010.png';

	$j( "input:checkbox[name^='gMapFilter']" ).after( function() {
		if( !this.id ) { return ''; } // no id, cant do anything

		var checkedImg = checkImgChecked;
		if( !this.checked ) { checkedImg = checkImgUnChecked; }

		var jCheckBox = $j( this );
		jCheckBox.css( 'display', 'none' );

		var jImageCheckBox = $j( '<img src="' + checkedImg + '" border="0" id="fake_' + this.id + '" />' );

		var data = { jCheckBox: jCheckBox, jImageCheckBox: jImageCheckBox };
		jImageCheckBox.bind( 'click', data, function( vars ) {
			vars.data.jCheckBox.attr( 'checked', !vars.data.jCheckBox.attr( 'checked' ) );
			var checkedImg = checkImgChecked;
			if( !vars.data.jCheckBox.attr( 'checked' ) ) { checkedImg = checkImgUnChecked; }
			if (this.id == 'fake_gMapFilterTours') {
				$j('#gMapFilterToursBike').attr( 'checked', vars.data.jCheckBox.attr( 'checked' ) );
				$j('#gMapFilterToursClimb').attr( 'checked', vars.data.jCheckBox.attr( 'checked' ) );
				$j('#gMapFilterToursTrekk').attr( 'checked', vars.data.jCheckBox.attr( 'checked' ) );
				$j('#fake_gMapFilterToursBike').attr( 'src', checkedImg );
				$j('#fake_gMapFilterToursClimb').attr( 'src', checkedImg );
				$j('#fake_gMapFilterToursTrekk').attr( 'src', checkedImg );
			}
			if (this.id == 'fake_gMapFilterToursBike' || this.id == 'fake_gMapFilterToursClimb' || this.id == 'fake_gMapFilterToursTrekk') {
				$j('#gMapFilterTours').attr( 'checked', false );
				$j('#fake_gMapFilterTours').attr( 'src', checkImgUnChecked );
			}
			vars.data.jCheckBox.triggerHandler( 'click' );
			vars.data.jImageCheckBox.attr( 'src', checkedImg );
		} ) ;

		return jImageCheckBox;
	} );
	// END change checkboxes to ImageCheckBoxes

	skiinfoMap = new SkiinfoMap();

	skiinfoMap.addListener("ViewportInitialized", function() {
		GEvent.bind( map, "moveend", skiinfoMap, skiinfoMap.handleMoveEnd );
		GEvent.bind( map, "zoomend", skiinfoMap, skiinfoMap.handleZoomEnd );
		GEvent.bind( map, "click", skiinfoMap, skiinfoMap.handleClick );
	}, skiinfoMap );

	skiinfoMap.initialize();

});
