var map, popup; // map and popup objects

var pano, flickr; // panoramio and flickr layers

var spinnerMarker; // The marker used for the spinning animation

var defIconHeight = 32;
var defIconWidth = 32;

var lat = gup( 'lat' )
var lon = gup( 'lon' )
var zoom = gup( 'zoom' )

var epsg4326 = new OpenLayers.Projection("EPSG:4326");

if( lat == "" )
{
  lat=50.6
  lon=9.7
  zoom=6
}
else
{
	lat=parseFloat(lat)
	lon=parseFloat(lon)
	zoom=parseInt(zoom)
}        

function gup( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
	return "";
  else
	return results[1];
}


/**
 * Function: log
 * A logging function for debugging purposes
 * @param {String} output The output string that should be added to the "debug console"
 */
function log(output) {
    document.getElementById('eventlog').innerHTML += output + '<br />';
}


/**
 * Function: getAndDisplayMarkers
 * Remove all current markers, get new markers via JSON and display them using JQuery + the abstraction provider
 */
function getAndDisplayMarkers(){    
    //Close any Popup that might still be open
    closeMapPopup();
       
    //Remove the current marker layer
    if (pano) {
        pano.destroy();
		flickr.destroy();
    }
    
	// Welcome the Phoenix! Create a brand new Panoramio-layer and add it to the map
	pano = new OpenLayers.Layer.Markers( "Panoramio" );
    map.addLayer(pano);
	
	// Introducing Phoenix's brother! Another Flickr-layer and add it to the map
	flickr = new OpenLayers.Layer.Markers( "Flickr" );
    map.addLayer(flickr);
    
    // Add a fake marker centered on the map with the spinning icon as long as the JSON is in progress
    spinnerMarker = addMarkerToMap(map.getCenter(), "images/spinner4-bluey.gif", null, 32, 32, pano);	
	
	// Get JSON object from Panoramio and execute callback function if successfull - http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
    $.getJSON( "http://www.panoramio.com/map/get_panoramas.php?order=popularity&set=public&from=0&to=60&minx=" + getMapExtent().toArray()[0] + "&miny=" + getMapExtent().toArray()[1] + "&maxx=" + getMapExtent().toArray()[2] + "&maxy=" + getMapExtent().toArray()[3] + "&size=square&callback=?", 
		function ( data ) {
			if (data.photos != null) {
				// Add a marker for each marker returned in the JSON object ($) if the marker-array is not empty
				$.each( data.photos, function( i, item ) {
					
					var popupcontent = "<a href='http://www.panoramio.com/photo/" + item.photo_id + "'><img src='http://mw2.google.com/mw-panoramio/photos/medium/" + item.photo_id + ".jpg' alt='"+item.photo_title+"' class='preview' /><br /><img src='images/panoramio-marker.png' alt='Panoramio' class='providericon panoramio' /> ";
					
					if (item.photo_title.length > 80)
						popupcontent += item.photo_title.substring(0,76) + "...</a>";
					else
						popupcontent += item.photo_title + "</a>";
					
					// Adds the marker to the marker layer using the magical addMarkerToMap (see below)					
					addMarkerToMap(new OpenLayers.LonLat(item.longitude, item.latitude).transform(epsg4326, map.getProjectionObject()), item.photo_file_url, popupcontent , 32, 32, pano);
					});
			}
			
			// Remove the spinner marker from the map once all marker object have been parsed
			if (spinnerMarker) {
				pano.removeMarker(spinnerMarker);
			}	
		}
		);
		
		
	var currentDate = new Date();
	var time = currentDate.getTime();
	// Get JSON object from Flickr and execute callback function if successfull - http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
	// TODO: geo_context=2 (Outdoor Bilder)
    $.getJSON( "http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=75b1c8e226b587bd99e922143252bd3a&bbox=" + getMapExtent().toArray()[0] + "%2C" + getMapExtent().toArray()[1] + "%2C" + getMapExtent().toArray()[2] + "%2C" + getMapExtent().toArray()[3] + "&format=json&per_page=60&min_date_upload="+(time-(1000*60*60*24*365))+"&extras=geo&callback=?");
};

function jsonFlickrApi(data){
	if (data.photos.total > 0) {
		$.each( data.photos.photo, function( i, item ) {		
			// Adds the marker to the marker layer using the magical addMarkerToMap (see below)		
			addMarkerToMap(new OpenLayers.LonLat(item.longitude, item.latitude).transform(epsg4326, map.getProjectionObject()), "http://farm"+item.farm+".static.flickr.com/"+item.server+"/"+item.id+"_"+item.secret+"_s.jpg", "<a href='http://www.flickr.com/photos/" + item.owner + "/" + item.id + "'><img src='http://farm"+item.farm+".static.flickr.com/"+item.server+"/"+item.id+"_"+item.secret+"_m.jpg' alt='"+item.title+"' class='preview' /><br /><img src='images/flickr_icon.png' alt='Flickr' class='providericon' />" + item.title + "</a>", 32, 32, flickr);	
		});
	}  
}

/**
 * Function: updateBound
 * If the map has been moved issue a new JSON GET  to get the markers for the new map viewport
 */
function updateBound()
{   
    var clusterOn;
    if ($('#clusterOn:checked').val() != null) {
        clusterOn = 1;
    } else {
        clusterOn = 0;
    }	
		
    // Issue JSON call width map extents
    getAndDisplayMarkers();
}

function getMapExtent(extent) {
   return map.getExtent().clone().transform(map.getProjectionObject(), epsg4326);
}

/**
 * Function: addMarkerToMap
 * Add a new marker to the markers layer given the following lonlat, 
 *     popupClass, and popup contents HTML. Also allow specifying 
 *     whether or not to give the popup a close box.
 * 
 * Parameters:
 * @param   {<OpenLayers.LonLat>} position -Where to place the marker
 * @param  {String} icon The relative (absolute?) path to the icon image ressource
 * @param  {String} description What to put in the popup
 * @param  {String} iconWidth  (optional) icon width in pixels (defaults to 32)
 * @param  {String} iconHeight  (optional) icon height in pixels (defaults to 32) 
 * @param  {String} horizontaloffset (optional) horizontal offset in pixels (defaults to center width)
 * @param  {String} verticaloffset (optional) vertical offset in pixels (defaults to bottom)
 */
function addMarkerToMap(position, icon, description, iconWidth, iconHeight, layer, horizontaloffset, verticaloffset) {    
    //Default icon width and height if parameters are empty
    iconHeight = iconHeight || defIconHeight; 
    iconWidth = iconWidth || defIconWidth;
    
    // Calculate default icon offset if parameters are empty
    var size = new OpenLayers.Size(iconWidth, iconHeight);    
    horizontaloffset = horizontaloffset || -(size.w/2);
    verticaloffset = verticaloffset || -size.h; 
    var offset = new OpenLayers.Pixel(horizontaloffset, verticaloffset);
     
	var MarkerIcon = new OpenLayers.Icon(icon, size, offset);
	
	//if ( icon.indexOf('spinner') == -1 )
	if ( icon.indexOf('spinner') > 0 )
		$(MarkerIcon.imageDiv).css({ 'border' : '0px' });
	else if (layer == pano)
		$(MarkerIcon.imageDiv).css({ 'border' : '1px #0071BB solid' });		
	else if (layer == flickr)	
		$(MarkerIcon.imageDiv).css({ 'border' : '1px #FF0084 solid' });	
	 
    // Create the marker and add it to the given layer
    var marker = new OpenLayers.Marker(position, MarkerIcon );
    marker.setOpacity(0.85);
	layer.addMarker(marker);
    
    // If there is  a description create a popup containing it
    if (description) {
        marker.events.register("click", marker, function() { openMapPopup(marker, description) });
    }

    return marker;
}

/**
 * Function: addMarkerToMap
 * Add a new marker to the markers layer given the following lonlat, 
 *     popupClass, and popup contents HTML. Also allow specifying 
 *     whether or not to give the popup a close box.
 * 
 * Parameters:
 * @param   {<OpenLayers.LonLat>} position -Where to place the marker
 * @param {<OpenLayers.Class>}  popupClass Which class of popup to bring up 
 *     when the marker is clicked.
 * @param  {String} icon The relative (absolute?) path to the icon image ressource
 * @param  {String} description What to put in the popup
 * @param  {String} iconWidth  (optional) icon width in pixels (defaults to 32)
 * @param  {String} iconHeight  (optional) icon height in pixels (defaults to 32) 
 * @param  {String} horizontaloffset (optional) horizontal offset in pixels (defaults to center width)
 * @param  {String} verticaloffset (optional) vertical offset in pixels (defaults to bottom)
 */
function openMapPopup(marker, description) {
   closeMapPopup();

   popup = new OpenLayers.Popup.AnchoredBubble("popup", marker.lonlat, null,
                                               description, marker.icon, true);
   popup.setBackgroundColor("#FFFFFF");
   popup.autoSize = true;
   map.addPopup(popup);

   return popup;
}

function closeMapPopup() {
   if (popup) {
      map.removePopup(popup);
      delete popup;
   }
}


function lokiMe() {
	// Loki stuff
	if (LokiAPI.isInstalled()) { 
		var loki = LokiAPI();
		loki.onSuccess = function(location) {
			var lonLat = new OpenLayers.LonLat(location.longitude, location.latitude).transform(epsg4326, map.getProjectionObject());

			map.setCenter (lonLat, 13);}
		loki.onFailure = function(error) {alert('Loki error: '+ error + ' - More Information about this geolocation feature at www.loki.com.')} 
		loki.setKey('broadbox.de');
		loki.requestLocation(true,loki.NO_STREET_ADDRESS_LOOKUP); 
	}
}

$(document).ready(function(){	
	// Create the map object...
	var options = options || {};

	map = new OpenLayers.Map("map", {
      controls: options.controls || [
         new OpenLayers.Control.ArgParser(),
         new OpenLayers.Control.Attribution(),
         new OpenLayers.Control.Navigation(),
         new OpenLayers.Control.PanZoomBar(),
         new OpenLayers.Control.ScaleLine(),
		 new OpenLayers.Control.Permalink()
      ],
      units: "m",
      maxResolution: 156543.0339,
      numZoomLevels: 20,
      displayProjection: epsg4326
   });

   var mapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik", {
      displayOutsideMaxExtent: true,
      wrapDateLine: true
   });

   var osmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender", {
      displayOutsideMaxExtent: true,
      wrapDateLine: true
   });

   var cyclemap = new OpenLayers.Layer.OSM.CycleMap("Cycle Map", {
      displayOutsideMaxExtent: true,
      wrapDateLine: true
   });

	// ...and finally add them to the map object.
	map.addLayers([mapnik,osmarender,cyclemap]);
	
	// Add a layer switcher outside the map
	map.addControl(new OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher')}));

	var lonLat = new OpenLayers.LonLat(lon, lat).transform(epsg4326, map.getProjectionObject());

	// Observe the map and notify ... when the map was moved
    map.events.register("moveend", map, updateBound);
	
	if (!map.getCenter())
	  map.setCenter (lonLat, zoom);

	$(".btn-slide").click(function(){
		$("#panel").slideToggle("slow");
		$(this).toggleClass("active"); return false;
	});
	
	if (LokiAPI.isInstalled()) { 
		// Add  Loki button to the Openlayers map object
	    $("#map_OpenLayers_ViewPort").append("<div id='PhotosmControls' class='olControlSelect' style='position: absolute; left: 8px; top: 160px; z-index: 1006;'></div>");
	    $("#PhotosmControls").append("<div id='LokiMe' style='position: absolute; left: 8px; top: 160px; z-index: 1006;'><a href='javascript:lokiMe()'><img id='LokiButton' style='position: relative; width: 26px; height: 25px;' src='images/loki_marker.png' alt='Locate me' class='providericon' /></a></div>");
	}
	
	$('#windowOpen').bind(
		'click',
		function() {
			if($('#window').css('display') == 'none') {
				$(this).TransferTo(
					{
						to:'window',
						className:'transferer2', 
						duration: 400,
						complete: function()
						{
							$('#window').show();
						}
					}
				);
			}
			this.blur();
			return false;
		}
	);
	$('#windowClose').bind(
		'click',
		function()
		{
			$('#window').TransferTo(
				{
					to:'windowOpen',
					className:'transferer2', 
					duration: 400
				}
			).hide();
		}
	);
	$('#windowMin').bind(
		'click',
		function()
		{
			$('#windowContent').SlideToggleUp(300);
			$('#windowBottom, #windowBottomContent').animate({height: 10}, 300);
			$('#window').animate({height:40},300).get(0).isMinimized = true;
			$(this).hide();
			$('#windowResize').hide();
			$('#windowMax').show();
		}
	);
	$('#windowMax').bind(
		'click',
		function()
		{
			var windowSize = $.iUtil.getSize(document.getElementById('windowContent'));
			$('#windowContent').SlideToggleUp(300);
			$('#windowBottom, #windowBottomContent').animate({height: windowSize.hb + 13}, 300);
			$('#window').animate({height:windowSize.hb+43}, 300).get(0).isMinimized = false;
			$(this).hide();
			$('#windowMin, #windowResize').show();
		}
	);
	$('#window').Resizable(
		{
			minWidth: 200,
			minHeight: 60,
			maxWidth: 750,
			maxHeight: 400,
			dragHandle: '#windowTop',
			handlers: {
				se: '#windowResize'
			},
			onResize : function(size, position) {
				$('#windowBottom, #windowBottomContent').css('height', size.height-33 + 'px');
				var windowContentEl = $('#windowContent').css('width', size.width - 25 + 'px');
				if (!document.getElementById('window').isMinimized) {
					windowContentEl.css('height', size.height - 48 + 'px');
				}
			}
		}
	);
});