// Gets the value of a passed param in the url.
function getUrlParam(name)
{
	if (typeof name != 'undefined' && name != '') {
		name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
		
		var 	regexS 	= "[\\?&]"+name+"=([^&#]*)",
				regex 	= new RegExp(regexS),
				results 	= regex.exec(window.location.href);
			
		if(results == null) {
			return results;
		} else {
			return results[1];
		}
	}
}

function urldecode( str ) {
    // Decodes URL-encoded string
    // +    discuss at: http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_urldecode/
    // +       version: 901.1411
    // *     example 1: urldecode('Kevin+van+Zonneveld%21');
    // *     returns 1: 'Kevin van Zonneveld!'
    // *     example 2: urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F');
    // *     returns 2: 'http://kevin.vanzonneveld.net/'
    // *     example 3: urldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a');
    // *     returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'
    
    var histogram = {};
    var ret = str.toString();
    
    var replacer = function(search, replace, str) {
        var tmp_arr = [];
        tmp_arr = str.split(search);
        return tmp_arr.join(replace);
    };
    
    // The histogram is identical to the one in urlencode.
    histogram["'"]   = '%27';
    histogram['(']   = '%28';
    histogram[')']   = '%29';
    histogram['*']   = '%2A';
    histogram['~']   = '%7E';
    histogram['!']   = '%21';
    histogram['%20'] = '+';

    for (replace in histogram) {
        search = histogram[replace]; // Switch order when decoding
        ret = replacer(search, replace, ret) // Custom replace. No regexing   
    }
    
    // End with decodeURIComponent, which most resembles PHP's encoding functions
    ret = decodeURIComponent(ret);

    return ret;
}

function cleanStringForOuput(string) {
	return string.replace(/\r\n/g, "<br />");;
}

function getSearchTypes() { return search_types; }

function clearMarkers() {
	var map	= getMapObject();
	map.clearOverlays();
}

function addDefaultFields(form_element) {
	HTML	= '';
	HTML	+= '<div class="zia-form-element-wrapper">' + "\r\n";
	HTML	+= '<label for="search-address" class="text required">Enter your city and state or ZIP Code to find a Restaurant, Venue, or Event.</label><span class="zia-form-element-separator"></span><br />' + "\r\n";
	HTML	+= '<input type="text" name="search-address" id="search-address" value="" class="text required search-address">' + "\r\n";
	HTML  += '<input type="image" name="submit" id="submit" src="/assets/images/icons/search_icon.gif" class="image small-submit inline-submit">' + "\r\n"
	HTML	+= '</div>' + "\r\n";
	HTML	+= '<div id="multiple-interests" class="multiple-interests">Choose multiple interests<br /><a href="#" class="search-values-select-all">Select All</a> | <a href="#" class="search-values-select-none">Deselect All</a><br /></div>' + "\r\n";
	$(form_element).append(HTML);
	return true;
}

function addSubmit(form_element) {
	HTML	= '';
	HTML	+= '<div class="zia-form-element-wrapper">' + "\r\n";
	HTML	+= '<input type="image" name="submit" id="submit" src="/assets/images/button/search.gif" class="image large-submit">' + "\r\n";
	HTML	+= '</div>' + "\r\n";

	$(form_element).append(HTML);
	return true;
}

function buildSearchForm(form_element) {
	addDefaultFields(form_element);
	buildOptionFields(form_element);
	addSubmit(form_element);
}

function buildOptionFields(form_element) {
	var search_types	= getSearchTypes();
	$(form_element).wrapInner('<div class="search-form-options">');
	
	for (type in search_types) {
		if (search_types[type]['children']) {
			buildGroupedOptionField(search_types[type], '.search-form-options');
		} else {
			buildOptionField(search_types[type], '.search-form-options');
		}
	}
}

function getMapObject() { return global_map; }
function getMapData() { return global_map_data; }
function getSearchRadius() { return search_radius; }
function getMarkers() { return saved_markers; }
function getSearchResultCount() { return search_result_count; }
function saveSearchResultCount() { search_result_count	= search_result_count + 1; }

function clearSearchResultCount() {
	search_result_count	= 0;
	current_points			= new Array();
}

function getPointByUniqueId(type, value) {
   var   map_data = getMapData(), 
         point    = '';

   // Check if passed type is foundin the global data.
   if (map_data[type]) {
   
      // Iterate over each item and look for a match.
      for (i = 0; i < map_data[type].length; i++) {
         
         if ((map_data[type][i].id + map_data[type][i].address.latitude + map_data[type][i].address.longitude) == value) {
            point = map_data[type][i];
         }
      }
   }
   
   return point;
}

function getPointBy(type, value) {
   var   map_data = getMapData(), 
         point    = '';

   // Check if passed type is foundin the global data.
   if (map_data[type]) {
   
      // Iterate over each item and look for a match.
      for (i = 0; i < map_data[type].length; i++) {
         
         if (map_data[type][i].title == value) {
            point = map_data[type][i];
         } else { alert(
            'search title: ' + map_data[type][i].title + "\r\n" + 
            'point title: ' + value 
         ); }
      }
   }
   
   return point;
}

function getMarkerByPoint(point) {
   var   markers  = getMarkers();
   for (i=0; i< markers.length; i++) {
      if (markers[i].title == point.title) {
         return markers[i];
      }
   }
}

// Expand here if needed.
function getInfoWindowHtml(point) { return cleanStringForOuput(point.html); }

function hideBubbleFullDescription(element) {
	parent_el	= $(this).parent();
	parent_parent_el	= $(parent_el).parent(); 

	$(parent_parent_el + ' .bubble-html-copy-description_full').fadeOut('fast', function() {
		// Switch the footers.
		$(parent_el + ' .bubble-html-footer').hide('fast', function(){
			$(parent_el + ' .bubble-html-footer-short').fadeIn('fast');
		});
		
		// Show the full description copy.
		$(parent_parent_el + ' .bubble-html-copy-description').fadeIn('slow');
	});
}

function showBubbleFullDescription(element) {
	var map_object	= getMapObject(),
	info_window		= map_object.getInfoWindow();
	info_window.maximize();
	return false;
}

function directionSearchHandler(form_wrapper_element, form_element) {
	var search_data   = '';

	// Iterate over the fields and find one with a value.
	$(form_element + ' .start-address-field').each(function(){
		current_value = $(this).val();
		if (current_value && typeof current_value != 'undefined' && current_value != '') {
			search_data = current_value;
		}
	});

	// Process the search request if theres search data to use.
	if (search_data && typeof search_data != 'undefined' && search_data != '') {
		processDirectionsRequest(search_data);
	} else {
	   // alert('No search request found'); 
	}
}

function showBubbleGetDirections(element, form_element) {
   var form_wrapper_element	= $(element).parent().parent().find('.bubble-html-direction-search-form-wrapper');
	$(form_wrapper_element).toggle('fast');
	
	// Bind the form to a submit action.
	$(form_element).bind('submit', function(){
		directionSearchHandler(form_wrapper_element, form_element);
	});
}

function showGoogleSearchResults() {
   $('#side_bar').fadeOut('fast', function() {
      $('#side_bar > div').hide('fast');
      $('#side-bar-content-direction-search-results').show('fast');
      $('#side_bar').fadeIn('slow');
   });
}

function hideGoogleSearchResults() { $('#side-bar-content-direction-search-results').slideUp('fast'); }

function processDirectionsRequest(search_data) {

   global_direction_search.from  = search_data;
	var direction_query	= 'from: ' + global_direction_search.from + ' to: ' + global_direction_search.to,
       count = 0;
   $('#map').jmap('SearchDirections', {
         query					: direction_query,
         panel					:'#side-bar-content-direction-search-results-pane',
         returnType 			: 'getLocations',
         local					: 'en_US',
         clearLastSearch	: true,
         preserveViewport	: true
     }, function(result, options) {
		if (count ==  0) {
			var valid = Mapifies.SearchCode(result.getStatus());
			if (valid) {
				global_directions	= result;
				showGoogleSearchResults();
			} else {
			// alert(valid.message + '  ' + direction_query);
			}
		}
		count++;
   });		
}

function buildOptionField(type, form_element) {
	HTML	= '';
	HTML	+= '<div class="zia-form-element-wrapper">' + "\r\n";
	HTML	+= '<input type="checkbox" name="search-values" id="" value="' + type.name + '" class="checkbox">' + "\r\n";
	HTML	+= '<label for="search-values" checked="" class="checkbox">' + type.name + '</label>' + "\r\n";
	HTML	+= '</div>' + "\r\n";
	$(form_element).append(HTML);
	return true;
}

function buildGroupedOptionField(type, form_element) {
	/*	*/
	HTML	= '';
	HTML	+= '<div class="zia-form-element-wrapper div-grouped-parent">' + "\r\n";
	HTML	+= '<input type="checkbox" name="search-values" id="" value="' + type.name + '" class="checkbox grouped-parent">' + "\r\n";
	HTML	+= '<label for="search-values" checked="" class="checkbox">' + type.name + '</label>' + "\r\n";
	HTML	+= '</div>' + "\r\n";

	// Iterate over each child to make its own checkbox.
	for(child in type['children']) {
		HTML	+= '<div class="zia-form-element-wrapper div-grouped-child">' + "\r\n";
		HTML	+= '<input type="checkbox" name="search-values" id="" value="' + type['children'][child].name + '" class="checkbox grouped-child">' + "\r\n";
		HTML	+= '<label for="search-values" checked="" class="checkbox">' + type['children'][child].name + '</label>' + "\r\n";
		HTML	+= '</div>' + "\r\n";

		if (type['children'][child]['children']) {
         for(sub_child in type['children'][child]['children']) {
            HTML	+= '<div class="zia-form-element-wrapper div-grouped-child-child">' + "\r\n";
            HTML	+= '<input type="checkbox" name="search-values" id="" value="' + type['children'][child]['children'][sub_child].name + '" class="checkbox grouped-child-child">' + "\r\n";
            HTML	+= '<label for="search-values" checked="" class="checkbox">' + type['children'][child]['children'][sub_child].name + '</label>' + "\r\n";
            HTML	+= '</div>' + "\r\n";
         }
		}
	}
	$(form_element).append(HTML);
	return true;
}

function getRadius(miles, point) {
  	var 	lat   = point.lat(),
	 		lng   = point.lng(),
  			d2r   = Math.PI / 180,                // degrees to radians
  		   r2d   = 180 / Math.PI,                // radians to degrees
  			Clat  = (miles / 3963) * r2d,        // using 3963 as earth's radius
  			Clng  = Clat/Math.cos(lat * d2r);
  			
  	Clng = lng + (Clng * Math.cos(0));
  	Clat = lat + (Clat * Math.sin(0));
   return(new GLatLng(Clat,Clng));
}        

function updateAddressWithLatLng(entity_point) {
   $('#map').jmap('SearchAddress', {
      'query': entity_point.search_address,
      'returnType': 'getLocations'
   }, function(result, options) {
      var valid = Mapifies.SearchCode(result.Status.code);
      if (valid.success) {
         jQuery.each(result.Placemark, function(i, point){
            if (point) {
               this_point  = new GLatLng(point.Point.coordinates[1], point.Point.coordinates[0]);
               entity_point.lat	= this_point.lat();
               entity_point.lng	= this_point.lng();
               encoded_entity_data = $.toJSON(entity_point);
               
               // Blindly send reqeust to the controller to updat the entity with the new values.
               $.post('/map/wolf-map/update-entity-lat-lng', {'entity_data' : encoded_entity_data}, function(data){}, "json");
            }
         });
      }
   });
}

function showSearchedLocation(search_value, search_data_types) {
	var	map = getMapObject(),
			radius_miles	= getSearchRadius();

   // Set all search types if none passed.
   if (!search_data_types || typeof search_data_types == 'undefined' || search_data_types == '') {
      search_data_types	= getAllSearchTypes();
   }

	  $('#map').jmap('SearchAddress', {
			'query': search_value,
			'returnType': 'getLocations'
	  }, function(result, options) {
			var valid = Mapifies.SearchCode(result.Status.code);

			if (valid.success) {
			   var result_array  = new Array(result.Placemark[0]);
			   
				jQuery.each(result_array, function(i, point){
					if (point) {
					   var g_point  = new GLatLng(point.Point.coordinates[1], point.Point.coordinates[0]);
					
						$('#map').jmap('AddMarker',{
							'pointLatLng':[point.Point.coordinates[1], point.Point.coordinates[0]],
							'pointHTML':point.address,
							'centerMap':false,
							'centerMoveMethod': 'pan'
						  });
	
	               var	radius  	= getRadius(radius_miles, g_point),
                  		Cradius 	= g_point.distanceFrom(radius) * 0.000621371192,
                        d2r 		= Math.PI/180,                // degrees to radians
                        r2d 		= 180/Math.PI,                // radians to degrees
                        Clat 		= (Cradius/3963) * r2d,      // using 3963 as earth'sradius
                        Clng = Clat/Math.cos(g_point.lat() * d2r);
						
						// Create a bounds box per the radius set earlier.
						bounds = new GLatLngBounds(
							new GLatLng(g_point.lat()-Clat, g_point.lng()-Clng),
							new GLatLng(g_point.lat()+Clat, g_point.lng()+Clng)
						);
						
						// Set center and zoom in.
						map.setCenter(g_point, map.getBoundsZoomLevel(bounds)); 
						showMarkersByType(search_data_types, bounds, g_point);
					}
				 });
				
			} else {
				$('#search-address').val('Error: ' + valid.message);
			   return false;
			}
	  });
}

function getBaseIcon() {
   var icon = new GIcon();
   icon.image = 'http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/greencirclemarker.png';
   icon.iconSize = new GSize(17, 17);
   icon.iconAnchor = new GPoint(16, 16);
   icon.infoWindowAnchor = new GPoint(18, 7);
   return icon;
}

// Saves the marker data in a global object.
function saveMarker(marker, point) {
   point.marker   = marker;
   saved_markers.push(point);
}

function createLabeledMarker(label, point) {
   var  	marker_type = point.type,
       	icon        = getBaseIcon(),
			map_object  = getMapObject();

   marker_type    = marker_type.replace(/ /g, '-');
   marker_type    = marker_type.toLowerCase();
   icon.image     = '/assets/images/jmap/icons/' + marker_type + '.png';
   
   opts = { 
     "icon": icon,
     "clickable": true,
     "labelText": label,
     "labelOffset": new GSize(-17, -7)
   };

   var   latlng   = new GLatLng(point.lat, point.lng),
         marker   = new LabeledMarker(latlng, opts),
         map      = getMapObject();
   
   // Save the marker in the point.
   saveMarker(marker, point);   
         
   // Add the click event for this pont.
   GEvent.addListener(marker, "click", function() {
   	global_direction_search.to = latlng;   // Save for direction searches.

     	marker.openInfoWindowHtml(
      "" + getInfoWindowHtml(point) + "", {
     		maxContent	: cleanStringForOuput(point.html_enlarge)
     	});
   });

	info_window	= map_object.getInfoWindow();
	
   // Add the click event for this pont.
   GEvent.addListener(info_window, "maximizeend", function() {
		$('.bubble-html').css('width', '97%');
   });
   map.addOverlay(marker);      
}

function addMarkerToMap(point, test_point, label) {
	// Will need to build html.
   createLabeledMarker(label, point);
   return false;
}

function getSearchResults() { return search_results; } 

function showSearchResults(search_value, show_search) {
	$('#side_bar').fadeOut('fast', function(){
		$('#side_bar > div').hide('fast', function(){
			// Hide the search options.
	    	collapseSearchOptions(search_value, show_search);
			
			$('#side_bar').fadeIn('slow', function(){
				$('#side-bar-content-search-results').show('fast');
			});
		});
	});
}

function addToSearchResult(point, count) {
   var   search_result_html   = '',
         marker_type = point.type;

	saveSearchResultCount();
	
	marker_type    = marker_type.replace(/ /g, '-');
   marker_type    = marker_type.toLowerCase();

   search_result_html   += '<tr>' + "\r\n";
   search_result_html   += '<td valign="top" class="col-count">' + "\r\n";
   search_result_html   += '<div class="icon ' + marker_type + '">' + count + '</div>' + "\r\n";
   search_result_html   += '</td>' + "\r\n";
   search_result_html   += '<td valign="center" class="">' + "\r\n";
   search_result_html   += '<div >' + "\r\n";
   search_result_html   += '<a href="#" class="' + point.type + '" id="'+ point.id + point.address.latitude + point.address.longitude + '" onclick="searchResultLink(this); return false;">'; 
   search_result_html	+=  cleanStringForOuput(point.title);
   search_result_html	+=  '</a>' + "<br />\r\n";

   if (point.address.address1 && point.address.address1 != '') {
      search_result_html   += cleanStringForOuput(point.address.address1) + "<br/>\r\n";
   }
   
   if (point.address.city && point.address.city != '') {
      search_result_html   += cleanStringForOuput(point.address.city);
   }
   
   if (point.address.state && point.address.state != '') {
      search_result_html   += ", " + cleanStringForOuput(point.address.state);
   }
   
   if (point.address.postal_code && point.address.postal_code != '') {
      search_result_html   += " " + cleanStringForOuput(point.address.postal_code);
   }
   
   if (point.address.phone && point.address.phone != '') {
      search_result_html   += '<br/>P: ' + cleanStringForOuput(point.address.postal_code);
   }
   
   search_result_html   += '</div>' + "\r\n";
   search_result_html   += '</td>' + "\r\n";
   search_result_html   += '</tr>' + "\r\n";
   
   setTimeout(function(){
      $('.search-result-list').append(search_result_html);
   }, 600);
}

function searchDataForPoints(points, location_bounds, point, type) {
	var 	radius	= getSearchRadius(),
			meters_per_mile	= 1609.344,
	      true_count        = 0;

   for (i = 0; i < points.length; i++) {

      // Issue request to google to get the lat / lng vals & update entity.
      if (!points[i].lng && !points[i].lat) {
         updateAddressWithLatLng(points[i]);
      }
      
      // Check if the lat / lng exist and if w/in bounds of search point.
      else if (points[i].lng && points[i].lat) {
        	test_point  = new GLatLng(points[i].lat, points[i].lng);

			if (jQuery.inArray(points[i].id + points[i].lat + points[i].lng, current_points) == -1) {
				if (location_bounds && location_bounds.containsLatLng(test_point)) {
					true_count++;
					current_points.push(points[i].id + points[i].lat + points[i].lng);
					
					addMarkerToMap(points[i], test_point, current_points.length);
					addToSearchResult(points[i], current_points.length);
			   }
			}
      } 
   }
}

function showMarkersByType(search_types, location_bounds, point) {
   var   map_data = getMapData(),
         location_info_html;

   if (search_types.length == 0) {
   	var search_types_object	= getSearchTypes(),
   	   search_types   = new Array();
   	
   	for (i = 0; i < search_types_object.length; i++) {
   	   search_types[i]   = search_types_object[i].name;
   	}
   }

   $('.side-bar-content-search-results').html('<table class="search-result-list"></table>');

   for (type in search_types) {
      if (map_data[search_types[type]] && map_data[search_types[type]].length > 0) {
         searchDataForPoints(map_data[search_types[type]], location_bounds, point, search_types[type]);
      }
   }
}

function collapseSearchOptions(search_value, show_search) {
   $('.multiple-interests').hide('fast');
   $('.map-search-form :checkbox').hide('fast');
   $('.map-search-form :checkbox ~ label').hide('fast');
   $('.large-submit').hide();
   $('.small-submit').show('fast');
   $('#universal-locator.wrapper .zia-form-element-wrapper input.text').css('width', '208px');   

   setTimeout(function(){
      // Set search info.    
      if (show_search && show_search == 1) {
         location_info_html   =  '<span class="result-title">Found ' + getSearchResultCount() + ' locations near:</span>' + "<br />\r\n";
         location_info_html   += search_value;
      } else {
         location_info_html   =  '<span class="result-title">Found ' + getSearchResultCount() + ' locations.</span>' + "<br />\r\n";
      }
      
      $('.search-results-info').html(location_info_html);
   }, 500);
   
}

function showSearchOptions() {
   $('.small-submit').hide('fast');
	$('.map-search-form :checkbox').css({'display':'inline'});
   $('.map-search-form :checkbox ~ label').css({'display':'inline', 'width':'215px'});
   $('.map-search-form :checkbox').show('fast');
   $('.map-search-form :checkbox ~ label').show('fast');
   $('.multiple-interests').show('fast');
   $('.large-submit').show();
}

function parseStringFromUrl(string) { return string.replace(/\+/gi, ' '); }

function getAllSearchTypes() {
   var search_data_types = new Array();
   var i = 0;
   // Only pull the first form, there's a few duplicates in there.
	$(".map-search-form:eq(0) :checkbox").each(function(){
		search_data_types[i]	= $(this).val();
		i++;
	});
	return search_data_types;
}

function clearSearchResults() { $('.side-bar-content-search-results').html(""); }

function processSearchRequest(search_value, passed_types, show_search) {
	clearMarkers(); // Clear any existing markers.
	clearSearchResultCount(); 	// Clear any set counts.
	clearSearchResults();
	
	var 	search_data_types		= [],
			i 							= 0;
			
	// Allow override of type.
	if (passed_types && typeof passed_types != 'undefined' && passed_types != '') {
		search_data_types	= passed_types;
	}
	// Pull from form.
	else {
		// Iterate over each checkbox and find the submitted data.
		$(".map-search-form :checkbox").each(function(){
			if ($(this).attr('checked')) {
				search_data_types[i]	= $(this).val();
				i++;
			}
		});
	}
   showSearchedLocation(search_value, search_data_types);
   showSearchResults(search_value, show_search); 
}

function openMarker(point) {
   if (point.marker) {
     	point.marker.openInfoWindowHtml("" + getInfoWindowHtml(point) + "", {
     		maxContent	: cleanStringForOuput(point.html_enlarge)
     	});      
   }
}

// Move to a formated point data.
function moveToPoint(point) {
   $('#map').jmap("MoveTo", {mapCenter: [point.lat,point.lng], centerMethod: 'pan'}, function(){
      openMarker(point);
   });
}

function searchResultLink(element) {
   type  	   = $(element).attr('class');
   unique_id   = $(element).attr('id');
   point 	   = getPointByUniqueId(type, unique_id);
   marker	   = getMarkerByPoint(point);
   
   if (marker) { 
   	moveToPoint(marker); 
      global_direction_search.to = marker.marker.latlng_;   // Save for direction searches.
   }
}

// Centeral place to catch events from.
function pageEventCaptures() {
	// Search again link click event. Hides all side bar content and shows the search form.
	$('.search-again').bind('click', function(){
	   $('#side_bar').fadeOut('fast', function(){
         $('#side_bar > div').hide('fast');
         $('#side_bar').fadeIn('fast', function(){});
         $('.side-bar-content').show('fast', function(){showSearchOptions()});
		});
	});
	
	// Global print link click event.
	$('.global-print').bind('click', function(){ window.print(); });
	
	$('.map-search-form').submit(function () { 
	   var search_data   = $('.search-address').eq(2).val();
	   if (!search_data || search_data == '' || typeof search_data == 'undefined') { search_data   = $('.search-address').eq(1).val(); }
	   if (!search_data || search_data == '' || typeof search_data == 'undefined') { search_data   = $('.search-address').eq(0).val(); }
	   $('.search-address').val(""); // Reset all values here.
		
		if (search_data) {
			processSearchRequest(search_data, null, true);
			return false;
		} else {
			alert('Please enter an address to search from.' + "\r\n" + search_data);
			return false;
		}
  	});

	// Link to check all form options.	
	$('.search-values-select-all').bind('click', function(){
		$(".map-search-form :checkbox").attr('checked', 'checked');
	});
	
	// Link to un check all form options.
	$('.search-values-select-none').bind('click', function(){
		$(".map-search-form :checkbox").attr('checked', '');
	});
}
