/**
 * Resizes floated image containers to the size of the image
 */
$.fn.imageWidth = function(threshold) {
	/**
	 * Function takes a jquery object and a css property (called dimension) and determines how many pixels the item is
	 * @param {jQuery Object} $item The jQuery object we're looking at
	 * @param {String} dimension The CSS property name to look for
	 * @returns The width or height of the CSS property with 'px' removed
	 * @type Number
	 */
	var	determineDimension = function($item, dimension) {
		$item = $($item);
		if ($item.css(dimension)) {
			return parseInt($item.css(dimension).replace('px', ''), 10);
		} else {
			return 0;
		}
	};
	
	var	resizeImage = function($image, $parent, $container) {
		// Determine the width of the image along with borders and padding
		var imageWidth = $image.width();
		var paddingLeft = determineDimension($image, 'padding-left');
		var paddingRight = determineDimension($image, 'padding-right');
		var borderLeft = determineDimension($image, 'border-left-width');
		var borderRight = determineDimension($image, 'border-right-width');

		// Calculate total edge (padding and border) width and the total width (edge and image)
		var edgeWidth = paddingLeft + paddingRight + borderLeft + borderRight;
		var totalWidth = imageWidth + edgeWidth;

		// Determine parent width
		var parentWidth = $parent.width();

		// If the image is greater then the threshold times the parent width resize the image and the container width
		// Otherwise set the image left's div to the size of the image plus the edge
		if ((threshold * parentWidth) <= totalWidth) {
			var revisedWidth = parentWidth * threshold;
			var revisedImageWidth = revisedWidth - edgeWidth;

			$image.width(revisedImageWidth);
			$container.width(parseInt(revisedWidth, 10));
		} else {
			$container.width(totalWidth);
		}
	};

	return this.each(function() {
		// Threshold is the maximum width an image plus its border and padding can be 
		// in relation to its parent container
		var threshold = (threshold) ? threshold : 2/3;

		// Find image within div
		var $image = $('img', $(this));
		var $parent = $(this).parent();
		var $container = $(this);

		$image.each(function(index) {
			resizeImage($image, $parent, $container);
			$(this).load(function() {			
				resizeImage($image, $parent, $container);
			});
		});
	});		
};

/**
 * Builds pull quote divs assuming you've wrappted your content with a span with the class: pullquote-left or pullquote-right
 */
$.fn.pullQuote = function() {
	return this.each(function() {
		var contents = $.trim($(this).html());
		var firstCharacterCode = contents.charCodeAt(0);
		if (firstCharacterCode < 65 || firstCharacterCode > 96) {
			contents = '&hellip; ' + contents;
		}
		
		var lastCharacter = contents.charAt(contents.length - 1);
		if ("?!.".search(lastCharacter) < 0) {
			contents = contents + ' &hellip;';
		}
		var $parent = $(this).parent();
		var $pullquote = $('<div>').attr('class', $(this).attr('class')).html(contents);
		$parent.before($pullquote);
	});		
};

/**
 * Makes all children with the selected container the same height.
 * Uses min-height, except for IE6 where height is used instead.
 */
$.fn.same_height = function() {
	return this.each(function() {
		tallest_height = 0;
		
		$(this).children().each(function(index) {
			tallest_height = ($(this).height() > tallest_height) ? $(this).height() : tallest_height;
		});
		
		if ($.browser.msie == true && $.browser.version <= 6) {
			$(this).children().css('height', tallest_height);
		} else {
			$(this).children().css('min-height', tallest_height);
		};
	});		
};

/**
 * Makes the placeholder attribute on input items useful by emulating the behavior
 */ 
var placeholder = function() {

	if ('placeholder' in document.createElement('input')) return this;
	
	$('input[placeholder]').each(function(index) {
		$(this).val($(this).attr('placeholder')).addClass('placeholder')
			.focus(function() {
				if ($(this).val() === $(this).attr('placeholder')) {
			        $(this).val('').removeClass('placeholder');
				}
			})
			.blur(function() {
				if ($(this).val() === ''){
					$(this).val($(this).attr('placeholder')).addClass('placeholder');
				}
			});
	});

	// Clear the value on submit
	$('input[placeholder]').parents('form').each(function(index) {
		$(this).submit(function () {
			$(this).find('input[placeholder]').each(function(index) {
				if ($(this).val() === $(this).attr('placeholder')) {
					$(this).val('');
				}
			});
		});
	});
};


/**
 * Adds the class 'last' to the last list items, and the last table item in a row. 
 * Also adds alt class to odd table rows.
 */
var markupPrep = function() {
	var listPrep = function() {
		$('> li:first', 'ul, ol').addClass('first');
		$('> li:last', 'ul, ol').addClass('last');
		
		$('ul#nav ul:first li:first li:first', 'ul, ol').removeClass('first');
	};
	
	var	tablePrep = function() {
		$('table tr:even').addClass('alt');
		$('table td:last, table th:last').addClass('last');
	};
	
	listPrep();
	tablePrep();
};

/**
 *	Creates a "fly-out" menu
 */
$.fn.flyOutMenu = function () {

	$(this).find('.sub-nav > ul > li ').hover(
		function () {
			$(this).siblings('.open').removeClass('open');
			$('.sub-nav').removeClass('split');
			$(this).parents('.sub-nav').css('height', 'auto');	
			
			$(this).addClass('open');
			
			if ($(this).find('ul').size()) {
				$(this).parents('.sub-nav').addClass('split');
				var ul_height = $(this).find('ul').height();
				var subnav_height = $(this).parents('.sub-nav').height();
				if (ul_height > subnav_height) {
					$(this).parents('.sub-nav').addClass('split').css('height', ul_height+10);
				}
			}
			
			$(this).parents('.sub-nav').hover(null,function () {
				$(this).find('.open').removeClass('open');
				$(this).css('height', 'auto');
				$(this).removeClass('split');	
			});
		}
	);

	// Add .rollover on hover
	$(this).find('li li').hover(function() {
		$(this).addClass('rollover');
	}, function() {
		$(this).removeClass('rollover');
	});
	
}

/**
 * Rebuilds a select list into an unordered list
 */
$.fn.rebuildSelect = function () {	

	// Builds a hidden field with the selected default value, and field name
	var buildHiddenField = function ($ul) {
		// Get default value if it exists
		if($ul.find('.selected').size()) {
			value = $ul.find('.selected').attr('data-value');
		}
		else {
			value = $ul.find('li:first').attr('data-value');			
		}
		
		name = $ul.attr('data-name');
		
		$ul.after('<input type="hidden" name="'+name+'" value="'+value+'"/>');
	}
	
	// Reset the hidden field with value
	var resetHiddenField = function ($li) {
		
		// Get default value if it exists
		value = $li.find('.selected').attr('data-value');
		name = $ul.attr('data-name');
				
		$('input[name='+name+']').val(value);
	}
	
	// Rewrite the select element into a ul element
	var rewriteSelect = function ($select) {	
				
		// Get default value	
		var selected_value = $select.val();
		
		// Rewrite current Select element into a Ul element
		$select.find('option').each(function (index, option) {
			
			// Create the li elements
			$li = $(document.createElement("li"));
			$li.text($(option).text());
			$li.attr('data-value', $(option).attr('value'));
			
			// Add the 'selected' class to the default select value
			if (selected_value == $(option).attr('value')) {
				$li.addClass('selected');
			}
			$(option).replaceWith($li);
		});

		// Create the ul element
		var $ul = $(document.createElement("ul"));
		$ul.html($select.html());
		
		// Set default selected value
		if(!$ul.find('.selected').size()) {
			$ul.find('li:first').addClass('selected');
		}
		
		// Set UL's class to Select's class attribute
		$ul.addClass($select.attr('class'));
		$ul.attr('data-name', $select.attr('name'));
		$select.replaceWith($ul);
		
		return $ul;
	}
	
	// Initialize
	var $ul = rewriteSelect($(this).children('select'));
	buildHiddenField($ul);
	
	$ul.find('li').click(function () {
		
		// If UL is active, when an li is clicked reset the hidden field 
		// and hide the other list items.
		if ($ul.parent().hasClass('selectbox-active')) {
			$ul.parent().removeClass('selectbox-active');
			$ul.find('li.selected').removeClass('selected');
			$(this).addClass('selected');
			resetHiddenField($ul);
			$ul.find('li').hide();

			// Show the selected list element
			$ul.find('li.selected').show();
		}
		
		// If the selectbox is active, show LIs and make UL active
		else {
			$ul.parent().addClass('selectbox-active');
			$ul.find('li').show();

			// Add the check icon to the selected li
			$ul.find('li.selected');
		}
	});
}

map = function () {
	
	// Initialize Global Variables
	var map;
	var markersArray = [];
	var locations = [];
	var boxes = ".nav_categories input[type=checkbox]";
	
	/**
	*	Hide/Show map markers and list items based on the filter checkboxes
	*/
	var hideShowLocations = function () {

		var filter_categories = new Array();
		var marker_categories = new Array();
		var show_location = false;

		$(boxes).each(function() {
			if ($(this).attr('checked')) {
				filter_categories.push($(this).attr('name')); 
			}
		}); 
		
		// Hide/Show Markers
		for(var i=0;i<markersArray.length;i++) {
			var show_location = false;
			var marker_categories = markersArray[i].categories.split(' ');
			$.each(marker_categories, function (index, value) {
				if ($.inArray(value, filter_categories) != -1) {
					show_location = true;
				}
			});
			
			if (show_location) {
				markersArray[i].setVisible(true);
			}
			else {
				markersArray[i].setVisible(false);
			}
		}	
		
		// Hide/Show Listing
		$('li[data-categories]').each(function() {
			var show_location = false;
			var categories = $(this).attr('data-categories').split(' ');
			$.each(categories, function (index, value) {
				if ($.inArray(value, filter_categories) != -1) {
					show_location = true;
				}
			});
			
			if (show_location) {
				$(this).show();
			}
			else {
				$(this).hide();
			}
		});
	}
	
	var toggleAllBoxes = function (all_id, categories_id) {
		if ($(all_id).attr('checked')) {
			$(categories_id+' input[type=checkbox]').each(function() {
				$(this).attr('checked', true);
			});
		}
		else {
			$(categories_id+' input[type=checkbox]').each(function() {
				$(this).attr('checked', false);
			});
		}
	}
		
	/**
	*	Check all of the filter checkboxes
	*/
	var initializeBoxes = function (segment) {
		var default_categories = new Array();

		// Set defaults if data-default is not empty
		if (segment != '') {
			
			// Set the defaul categories from the url segment, stored in the data-default attribute
			default_categories = segment.split(':');
			
			$.each(default_categories, function (index, category) {
				$('input[name='+category+']').attr('checked', true);
			});
		}
		// Default will be all checkboxes if there is no default supplied in the segment
		else {
			
			// Set all checkboxes
			$('#all-products').attr('checked', true);
			$('#all-services').attr('checked', true);
			
			toggleAllBoxes('#all-products','#product-categories');
			toggleAllBoxes('#all-products','#service-categories');
			
		}
	}

	/**
	*	Draw the google map with markers and in info window pop-up
	*/
	var initializeGoogleMap = function () {
		var infowindow;
		var mapOptions = {
			mapTypeId: google.maps.MapTypeId.TERRAIN
	  	};
	
		map =  new google.maps.Map(document.getElementById("map"), mapOptions);
		
		setInitialZoom();
		
		google.maps.event.addListener(map, 'click', function() {
			if (infowindow) infowindow.close();
	    });
		
		
		$.getJSON('/locations/get-json-locations', function(data) {
			
			locations = data;
						
			// Build markers from json feed
			for(i=0;i < locations.length;i++) {
				
				var point = new google.maps.LatLng(locations[i].latitude,locations[i].longitude);
				var marker = new google.maps.Marker({
					position: point,
					title: locations[i].title,
					map: map
				});

				marker.categories = locations[i].categories;
				
				markersArray.push(marker);

				marker.infowindow_content = "<div class='infowindow'><h3><a href='"+locations[i].title_permalink+"'>"+locations[i].entry_title+"</a></h3><p>"+locations[i].address+"<br />"+locations[i].city+", "+locations[i].state+" "+locations[i].zipcode+"<br />"+locations[i].phone+"</p><p>"+locations[i].category_names+"</p><p><a  href='http://maps.google.com/maps?daddr="+locations[i].address+" "+locations[i].city+", "+locations[i].state+" "+locations[i].zipcode+"'><strong>Get Directions</strong></a><br /><a href='mailto:"+locations[i].email+"'><strong>Send Email</strong></a></div>";
				
			}
			
			infowindow = new google.maps.InfoWindow();
			
			for (var i = 0; i < markersArray.length; i++) {
				var marker = markersArray[i];
				google.maps.event.addListener(marker, 'click', function () {
					infowindow.setContent(this.infowindow_content);
					infowindow.open(map, this);
				});
			}
			
			hideShowLocations();
			
		});
	}
	
	/**
	*	Get the distance in km between two points
	*/
	var getDistance = function (lat1,lon1,lat2,lon2) {
				
		var R = 6371; // km (change this constant to get miles)
		var dLat = (lat2-lat1) * Math.PI / 180;
		var dLon = (lon2-lon1) * Math.PI / 180;
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
			Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
			Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		var d = R * c;

		return d;
	}
	
	/**
	*	Used in conjunction with .sort(sortByDistance) to sort an array
	*	of objects on the distance property.
	*/
	var sortByDistance = function (a, b) {
	    var x = a.distance;
	    var y = b.distance;
	    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
	}
	
	var searchMap = function (address) {
		var geocoder = new google.maps.Geocoder();
		
		// Contact google for the longitude and latitude
		if (geocoder) {
			geocoder.geocode({'address': address+' United States'}, function (results, status) {
				if (status == google.maps.GeocoderStatus.OK) {

					// Add distances to the array locations
					for(var i = 0; i < locations.length; i++) {
						locations[i].distance = getDistance(results[0].geometry.location.lat(), results[0].geometry.location.lng(), locations[i].latitude, locations[i].longitude);	
					}
					
					// Sort the locations on by distance asce
					locations.sort(sortByDistance);

					// Zoom in on first closest location
					var closestLocation = new google.maps.LatLng(locations[0].latitude, locations[0].longitude);
					
					map.setCenter(closestLocation);
					map.setZoom(10);
				}
				else {
					setInitialZoom();
				}
			});
		}
	}
	
	var setInitialZoom = function () {
		var centerCoords = new google.maps.LatLng(37.43, -78.65);
		map.setCenter(centerCoords);
		map.setZoom(6);
	}
	
	// Initialization
	initializeBoxes($('#map').attr('data-default'));	
	initializeGoogleMap();
	
	// Toggle on/off all checkboxes on click
	$('#all-products').click(function() {
		toggleAllBoxes('#all-products','#product-categories');
		hideShowLocations();
	});

	$('#all-services').click(function() {
		toggleAllBoxes('#all-services','#service-categories');
		hideShowLocations();
	});

	// Handle Filter Click
	$(boxes).click(function () {
		hideShowLocations();
	});

	// Location Search
	$('.go').click(function () {
		var address = $('.search.location').val();
		searchMap(address);
	});	
}

// Set up styled buttons to act as submit buttons in forms
function initSubmitButton () {
	$('form .button').click(function() {
		$(this).parents().filter('form').trigger('submit');
	});
	
	// Request a quote form, add a hidden input field containting the location on submit
	$('form[name=quote_form]').submit(function () {		
		$(this).prepend('<input type="hidden" name="location" value="'+$('#recipient_email option:selected').text()+'" />');
	});
}

/**
 * Email a page 
*/
function mailPage () {
	var body = $("textarea[name=body]").val();
	var to = $("input[name=to]").val();
	
	mail_str = "mailto:"+to+"?subject="+document.title;
	mail_str += "&body="+body+" ";
	mail_str += location.href; 
	location.href = mail_str;
}

function initColorBox () {

	if($('link[href$=ie6-only.css]').size() == 0) {
		$.getScript('/js/colorbox/jquery.colorbox-min.js', function () {
		
			// Color Box for "Request a Quote", Used Equipment image gallery, and Walkaround Request
			$('#pagination .colorbox').colorbox({transition:"none", width:"75%", height:"75%"});    
			$('.specifications .colorbox').colorbox({
				onComplete:function() {
					initSubmitButton();
				}
			});
			$('.used-detail .colorbox').colorbox({
				onComplete:function() {
					initSubmitButton();
				}
			});

			$('.colorbox-main').css('cursor','pointer');
			$('.colorbox-main').click(function () {
				$('.colorbox[rel=gallery]:first').trigger('click');
			});
		});
	}

}

$(document).ready(function() {
	placeholder();
	$('div.image-left, div.image-right').imageWidth();
	$('span.pullquote-left, span.pullquote-right').pullQuote();
	
	markupPrep();
	
	// Carousel on Home, Rentals, and Used Equipment landing pages
	$('ul#carousel-slides').innerFade({
		speed: 1000,
		timeout: 5000,
		indexContainer: '#carousel-navigation',
		callback_index_update: function() {
			Cufon.replace('ul#carousel-navigation p');
		}
	});
	
	// Main Navigation
	$('ul#nav').flyOutMenu();
	
	// Select Fields
	$('div.select-filter').each(function() {
		$(this).rebuildSelect();
	});

	if ($('.scrollable').size()) {
		// Featured Equipment on home page
		$(".scrollable").scrollable();
	}
	
	$('.prev, .next').each(function () {
		$(this).click(function(event) {
			event.preventDefault();
		})
	});
	
	// Initialize a form's submit button implemented as a hyperlink
	initSubmitButton();
	
	// Initialize the color boxes
	initColorBox();

	
	// Load map for locations
	if ($('#map').size()) {
		map();
	}
	
	// Show Email From
	$('.email-page-toggle').toggle(
		function () {
			$('.email-page').slideDown('slow');
		},
		function () {
			$('.email-page').slideUp('slow');
		}
	);
	
});

Cufon.replace('ul#carousel-navigation p');
