;(function($) {
	
	$.fn.page = function(options) {
		var selector = this.selector;
		return this.each(function() {
			var $this = $(this);
			var extendSelector = ($this.data("settings")) ? {} : {selector:selector, deeplinkingSet: false};
			
			$this.data("settings", $.extend(true, {}, $.fn.page.defaults, $this.data("settings"), extendSelector, options));
			var settings = $this.data("settings");
			$this.pageSetPagination();
			
			if (settings.deeplinkingEnabled && !settings.deeplinkingSet) {
				$this.data("settings").deeplinkingSet = true;
				var currentQuery = $.address.baseURL();
				if (currentQuery.indexOf("?") != -1) currentQuery = currentQuery.split("?")[1];
				if (currentQuery.indexOf("#") != -1) currentQuery = currentQuery.split("#")[0];
				$.address.change(function(event) {
					var newQuery = event.value.split("/")[1];
					$.log(newQuery, currentQuery);
					if (newQuery == currentQuery) return;
					currentQuery = newQuery;
					$this.deeplink(event.value);
				});
				
				// if ($.address.value() != "/") $this.deeplink($.address.value()); // too late for $.address.init() event
			}
		});
	};
	
	$.fn.pageTo = function(url) {
		return this.each(function() {
			var $this = $(this);
			var settings = $this.data("settings");
			if (settings.deeplinkingEnabled) {
				$.address.value(url.indexOf("?") > -1 ? url.split("?")[1] : url);
			}
			else {
				$this.pageLoad({url:url});
			}
		});
	};
	
	$.fn.deeplink = function(value) {
		return this.each(function() {
			if (value != "/") {
				if (value.indexOf("/") == 0) value = value.split("/")[1];
				var $this = $(this);
				var base = $.address.baseURL().split("?")[0];
				var delimiter = value != "" ? "?" : "";
				var url = base + delimiter + value;
				$.log("loading url", url);
				$this.pageLoad({url:url});
			}
		});
	};
	
	$.fn.pageLoad = function(options) {
		
		return this.each(function() {
			var $this = $(this);
			
			$this.page(options); // generate settings based on defaults
			settings = $this.data("settings");
			
			var $content = $(settings.contentSelector, $this);
			var $pagination = $(settings.paginationSelector, $this);
			
			if ($this.data("request")) $this.data("request").abort();
			settings.onBeforeLoad();
			$this.data("request", $.ajax({
				url:settings.url,
				data:settings.requestData,
				type:settings.method,
				success: function(data, status) {
					settings.onAfterLoad(data);
					var $loadedContent = $(settings.selector + settings.contentSelector, data);
					var $loadedPagination = $(settings.selector + settings.paginationSelector, data);
					
					if ($loadedPagination.length > 0) {
						if ($pagination.length > 0) {
							$pagination.animate({opacity:0}, settings.contentDuration, "swing", function() {
								$pagination.html($loadedPagination.html());
							});
						}
						else {
							$pagination = $loadedPagination.css({opacity:0}).appendTo(settings.selector);
							$this.pageSetPagination();
						}
					}
					else {
						$pagination.remove();
					}
					
					$content.animate({opacity:0}, settings.contentDuration, "swing", function() {
						function onComplete() {
							settings.onComplete(data);
							$content.html($loadedContent.html());
							$pagination.animate({opacity:1}, settings.contentDuration, "swing");
							$content.animate({opacity:1}, settings.contentDuration, "swing", function() {
								if ($content[0].style.removeAttribute) $content[0].style.removeAttribute("filter");
								settings.onAfterComplete();
							});
						}
						
						$this.css({position:"relative"});
						var $dummy = $content.clone().css({left:0, top:0, height:'auto', position:"absolute"}).html($loadedContent.html()).appendTo($content.parent());
						var height = $dummy.height();
						$dummy.remove();
						if ($this[0].style.removeAttribute) $this[0].style.removeAttribute("position");
						$.log($content.height(), height);
						if ($content.height() != height) {
							$content.animate({height:height}, settings.contentDuration, "swing", function() {
								$(this).css('height', 'auto');
								onComplete();
							});
						}
						else {
							onComplete();
						}
					});
				}
			}));
			
		});
	};
	
	$.fn.pageSetPagination = function() {
		return this.each(function() {
			var $this = $(this);
			var settings = $this.data("settings");
			
			$(settings.paginationSelector, $this).pagination({
				onChange: function(page) {
					$this.pageTo($(this).attr("href"));
				}
			});
		});
	};
	
	$.fn.page.defaults = {
		contentDuration:650,
		contentSelector: ">ul:not(.pagination)",
		deeplinkingEnabled: true,
		method: "GET",
		onBeforeLoad: function() {},
		onAfterLoad: function(data) {},
		onComplete: function(data) {},
		onAfterComplete: function() {},
		paginationSelector: ">ul.pagination",
		requestData: {}
	};
	
})(jQuery);
