if ( Object.isUndefined(CodeCompany) ) { var CodeCompany = {}; }

CodeCompany.MathHelp = {
	deg2rad: function(degrees)
	{
		return degrees * (Math.PI / 180);
	},
	
	distanceBetween: function(lat1r, lng1r, lat2r, lng2r)
	{
		R = 6371;
		
		retval = Math.acos(
			Math.sin(lat1r) * Math.sin(lat2r) +
			Math.cos(lat1r) * Math.cos(lat2r) *
			Math.cos(lng2r - lng1r)) * R;
			
		return Math.round(Math.abs(retval));
	}
}

CodeCompany.LocationFinder = Class.create({
	initialize: function() 
	{
		this.locations = [];
	},
	
	addLocation: function(latitude, longitude, locationData)
	{
		this.locations.push({ 
			latr: CodeCompany.MathHelp.deg2rad(latitude), 
			lngr: CodeCompany.MathHelp.deg2rad(longitude), 
			data: Object.extend({ lat: latitude, lng: longitude }, locationData) 
		});
	},
	
	findNearest: function(targetLat, targetLng, count, searchCriteria)
	{
		result = [];
		
		targetLatr = CodeCompany.MathHelp.deg2rad(targetLat);
		targetLngr = CodeCompany.MathHelp.deg2rad(targetLng);
		
		this.locations.select(function(location) {
			var matching = null;
			
			Object.keys(searchCriteria).each(function(key){
				var thisMatch = (location.data[key] == searchCriteria[key].value); 
				if ( matching == null ) 
				{ 
					matching = thisMatch; 
				}
				else
				{
					if ( searchCriteria[key].andedOn )
					{
						matching = matching && thisMatch;
					}
					else
					{
						matching = matching || thisMatch;
					}
				}
			});
			
			return (matching == null)?true:matching;
		}).each(function(location){
			result.push({ 
				distance: CodeCompany.MathHelp.distanceBetween(location.latr, location.lngr, targetLatr, targetLngr),
				location: location
			});
		},this);
		
		return result.sortBy(function(loc) { return loc.distance; }).slice(0,count);
	}
});