jQuery.fn.sortElements = (function(){

    var sort = [].sort;

    return function(comparator, getSortable) {

        getSortable = getSortable || function(){return this;};

        var placements = this.map(function(){

            var sortElement = getSortable.call(this),
                parentNode = sortElement.parentNode,

                // Since the element itself will change position, we have
                // to have some way of storing its original position in
                // the DOM. The easiest way is to have a 'flag' node:
                nextSibling = parentNode.insertBefore(
                    document.createTextNode(''),
                    sortElement.nextSibling
                );

            return function() {

                if (parentNode === this) {
                    throw new Error(
                        "You can't sort elements if any one is a descendant of another."
                    );
                }

                // Insert before flag:
                parentNode.insertBefore(this, nextSibling);
                // Remove flag:
                parentNode.removeChild(nextSibling);

            };

        });

        return sort.call(this, comparator).each(function(i){
            placements[i].call(getSortable.call(this));
        });

    };

})();


function toRad(d) {  // convert degrees to radians
	return d * Math.PI / 180;
}

function onFilterChange() {
	guestsList = jQuery("#guests")[0];
	if (!guestsList) {
		return;
	}

	selectedGuests = jQuery("#guests").val();
	if (selectedGuests.length) {
		selectedGuests = selectedGuests.split("_");
	}
	selectedDogs = jQuery("#dogs").val();
	selectedWifi = jQuery("#wifi").attr('checked');
	selectedSwimmingPool = $("#swimmingPool").attr('checked');

	selectedLocation = jQuery("#location").val();
	if (selectedLocation.length) {
		selectedLocation = selectedLocation.split(",");
	}
	if (selectedLocation.length == 1) {
		locationFilterType = "none";
		
	} else if (selectedLocation.length == 3) {
		locationFilterType = "circle";
		x = selectedLocation[0];
		y = selectedLocation[1];
		r = selectedLocation[2];

	} else if (selectedLocation.length == 4) {
		t = selectedLocation[0];
		l = selectedLocation[1];
		b = selectedLocation[2];
		r = selectedLocation[3];

		locationFilterType = "square";
	}

	

	cottages = jQuery(".cottage");

	cottageCount = 0;
	for (i=0; i<cottages.length; i++) {
		cottageItem = cottages[i];
		show = true;

		if (selectedWifi && jQuery(cottageItem).find('.cottage_wifi').val()*1 != 1) {
			show = false;
		}
		
		if (selectedSwimmingPool && jQuery(cottageItem).find('.cottage_swimming_pool').val()*1 != 1) {
			show = false;
		}

		if (selectedDogs.length > 0) {
			if (selectedDogs != jQuery(cottageItem).find('.cottage_pets').val()) {
				show = false;
			}
		}

		if (selectedGuests.length > 1) {
			selectedGuestsMin = selectedGuests[0]*1;
			selectedGuestsMax = selectedGuests[1]*1;

			cottageGuestsMin = jQuery(cottageItem).find('.cottage_sleeps_min').val();
			cottageGuestsMax = jQuery(cottageItem).find('.cottage_sleeps_max').val();
			if (cottageGuestsMax == 0) {
				cottageGuestsMax = 200;
			}

			show = show && cottageGuestsMax >= selectedGuestsMin;
			show = show && cottageGuestsMax <= selectedGuestsMax+2;
		}


		lat = jQuery(cottageItem).find('.cottage_latitude').val();
		lng = jQuery(cottageItem).find('.cottage_longitude').val();
		switch (locationFilterType) {
			case "circle":
				dlng = lng-x;
				dlat = lat-y;
				d = earthDistance(lat,lng,x,y);
				show = show && (d<r);
				break;
			case "square":
				show =  show && !(lat > t || lat < b || lng < l || lng > r);
				break;
		}

		if (jQuery(cottageItem).hasClass("featured")) {
			show = true;
		}

		if (show) {
			cottageCount++;
			cottageItem.style.display = "block";
		} else {
			cottageItem.style.display = "none";
		}
	}

	if (cottageCount==totalCottages) {
		jQuery("#cottageQty").html("Search cottages <span>(Showing all "+totalCottages+")</span>");
	} else {
		jQuery("#cottageQty").html("Search cottages <span>(Showing "+cottageCount+" of "+totalCottages+")</span>");
	}


	sortItem = jQuery("#sort").val();

	ascending = jQuery("#sortDirection").val() == "Ascending";

	cottagesGrid = jQuery("#cottageGrid")[0];
	cottages = cottagesGrid.childNodes;
	switch (sortItem) {
		case "Name":
			cottageSort(ascending,'.cottage_name',true);
			break;
		case "Price":
			cottageSort(ascending,'.cottage_price_min',false);
			break;
		case "Sleeps":
			cottageSort(ascending,'.cottage_sleeps_max',false);
			break;
//					case "Location":
//						valueSort(cottages,0,cottages.length-1,ascending,7);
//						break;
	}

}

function cottageSort(ascending, className, text) {
	$('.cottage').sortElements(function(a, b){
		var aVal = $(a).find(className).val();
		var bVal = $(b).find(className).val();
		if (!text) {
			aVal = aVal*1;
			bVal = bVal*1;
		}
		if (ascending) {
			return aVal > bVal ? 1 : -1;
		} else {
			return aVal < bVal ? 1 : -1;
		}
	});
}

function valueSort(cottages, start, rest, ascending, childNodeIndex) {
	for (var i = rest - 1; i >= start;  i--) {
		for (var j = start; j <= i; j++) {
			lessthan = cottages[j+1].childNodes[childNodeIndex].value*1 < cottages[j].childNodes[childNodeIndex].value*1;
			if ( (lessthan && ascending) || (!lessthan && !ascending) ) {
				//cottages[j+1].swapNode(cottages[j]);
			}
		}
	}
}


function reset() {
	jQuery("#guests").val('');
	jQuery("#dogs").val('');
	jQuery("#location").val(-1);
	jQuery("#wifi").attr('checked',0);
	jQuery("#swimmingPool").attr('checked',0);

	onFilterChange();
}

function earthDistance(lat1,lon1,lat2,lon2) {
	var R = 3963; // miles
	var dLat = toRad(lat2-lat1);
	var dLon = toRad(lon2-lon1);
	var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
			Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
			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;
}
