/* ******************************************************* */
/* JQuery Plugin, Page Filter                              */
/* Created By: Luke Hastie, Points Align Ltd               */
/* ******************************************************* */
(function($) {
	// Main interface
	$.fn.paPageFilterSettings = {
					filter: function() {return true},
					ignore: null,
					pager: null,
					pagerNext: null,
					pagerPrev: null,
					perPage: 9,
					pagesClass: 'paPages',
					pageClass: 'paPage',
					pageActiveClass: 'Current',
					pagerAnchorBuilder: function(idx, slide) { 
						return '<a href="#"></a>'; 
					},
					effect: 'scrollHorz',
					effectSpeed: 1000,
					loading: null
	};
	$.fn.paPageFilter = function() {
		
		var settings = $.fn.paPageFilterSettings;
		
	
		var $this	= undefined;
		var $pages = undefined;
		
		//private
		var $$ = {
			startCycle: function() {
				var pageState = jQuery.bbq.getState();
				if (!pageState[$this.attr("id")])
					pageState[$this.attr("id")] = 0;
				if (pageState[$this.attr("id")] < 0 || pageState[$this.attr("id")] > $pages.children().length) 
					pageState[$this.attr("id")] = 0;
					
				settings.pager.html("");
				if ($pages.children().length > 1) {
					$pages.cycle({
						fx:     settings.effect,
						speed: settings.effectSpeed,
						timeout: 0,
						pause: 1,
						fastOnEvent: 250, 
						cleartype: 1,
						cleartypeNoBg: true,
						activePagerClass: settings.pageActiveClass,
						pager:   settings.pager,
						pagerAnchorBuilder: settings.pagerAnchorBuilder,
						prev: settings.pagerPrev,
						next: settings.pagerNext,
						startingSlide: pageState[$this.attr("id")],
						after: function(curr, next, opts, fwd){
							var index = opts.currSlide;
							//Bug in jquery cycle, determine slide manually
							for (var i=0; i<$pages.children().length; i++){
								var $page = $($pages.children()[i]);
								if ($page && $page.is(":visible")) {
									index = i;
									break;
								}
							}
							//settings.pagerPrev[index == 0 ? 'hide' : 'show']();
							//settings.pagerNext[index == opts.slideCount - 1 ? 'hide' : 'show']();
							//get the height of the current slide
							
							if (settings.effect == 'none'){
								var ht = $($pages.children()[index]).height();
								//set the container's height to that of the current slide
								
								if (ht > 0)
									$(this).parent().css({height: ht});
							} 
							
							var pageState = jQuery.bbq.getState();
							pageState[$this.attr("id")]=index;
							setTimeout(function(){jQuery.bbq.pushState(pageState,2);}, 100);
						}
						
					});
				};
			},
			stopCycle: function() {
				$pages.cycle('stop', {destroy: true});
				$pages.css({width: '', position: ''});
				$pages.children().css({height: '', width: '', position: ''});
			},
			log: function(msg) {
				if (false && console && console.log && typeof console.log === "function") {
					console.log(msg);
				}
			}
		}
		

		var public = {
			init: function(){

				$this = $(this);
				// Check Pager to see if its a string and map it
				if ( typeof settings.pager === 'string') 
					settings.pager = $(settings.pager);
				
				if ( typeof settings.ignore === 'string') 
					settings.ignore = $(settings.ignore);
				
				if ( typeof settings.pagerNext === 'string') 
					settings.pagerNext = $this.find(settings.pagerNext);
				
				if ( typeof settings.pagerPrev === 'string') 
					settings.pagerPrev = $this.find(settings.pagerPrev);
								
				if (!settings.pager || typeof settings.pager === 'string')
					return false;
				
				//check for perPage in the rel tag
				var rel = $this.attr("rel");
				if (rel) 
					settings.perPage = rel;
					
				$this.data("settings", settings);
				
				//Copy items to page - pager
				if (!$this.data("items") || $.isEmptyObject($this.data("items"))) {
					$this.data("items", $this.children().filter(function(){
						if (typeof settings.ignore === 'object')
							return $(this)[0] !== settings.ignore[0];
						else 
							return true;
					}));
				}
				
				
			},
			start : function() {
				//remove items from DOM
				var ht = $this.height();
				if (ht > 0)
					$this.css("height", ht);
				$this.data("items").detach();
				
				//add pages div
				public.filter( );
				$this.css("height", "");
			},
			stop : function() { 
				//get saved settings

				$$.stopCycle();

				$pages = $this.find("." + settings.pagesClass);
				$pages.remove();
				
				settings.pager.html("");
				$this.data("items").insertBefore(settings.pager)
			},
			filter : function(a) {
			
				$pages = $this.find("." + settings.pagesClass);
				if ($pages.length == 0) {
					$pages = $("<div class='" + settings.pagesClass + "'></div>").prependTo($this);
				}
				
				$$.stopCycle();
				
				var pFilter = function() {
					
					var ht = $pages.height();
					if (ht != 0)
						$pages.css("height", ht);
					

					$pages.children().detach();//.html("");
					
					var $items = $this.data("items").filter(settings.filter);
					var records = $items.length;
					var noOfPages = records / settings.perPage;
					
					// round noOfPages
					if (noOfPages < 1 )
						noOfPages = 1;
					else if (noOfPages % 2 < 0)
						noOfPages +=1;

					if (noOfPages == 1) {
						if (settings.pagerPrev) 
							settings.pagerPrev.css({visibility: 'hidden'});
						if (settings.pagerNext) 
							settings.pagerNext.css({visibility: 'hidden'});
					} else {
						if (settings.pagerPrev) 
							settings.pagerPrev.css({visibility: 'visible'});
						if (settings.pagerNext) 
							settings.pagerNext.css({visibility: 'visible'});
					}
					var pageState = jQuery.bbq.getState();
					if (!pageState[$this.attr("id")])
						pageState[$this.attr("id")] = 0;
					
						
					for(var i=0;i<noOfPages;i++){
						var $page = $("<div class='" + settings.pageClass + "'></div>");//.appendTo($pages);
						for(var j=0;j<settings.perPage;j++){
							var index = j + (i * settings.perPage);
							if (index < records) 
								$page.append($items[index]);							
						}
						if ($items.length == 0) {
								$page.append($("<div class='noResults'>No results found.</div>"));
						}
						if (pageState[$this.attr("id")] == i) {
							$page.children().css("display", "block");
						} else {
							$page.children().css("display", "none");
						}
						$page.append($("<div style='clear: left'></div>"));
						$page.appendTo($pages);
						
					}
					
					//$pages.css("height", "");
					
					// cycler
					//if (noOfPages>1 && !settings.loading)
						$$.startCycle();
					
					/*
					else if (noOfPages==1) {
						if (settings.pager)
							settings.pager.hide();
						if (settings.effect == 'none') {
							var ht = $pages.children().first().height();
							$pages.height(ht);
						}
					}
					*/
					//unhide any hidden ones
					$pages.find("." + settings.pageClass).children().css("display", "block");
					if (a && !settings.loading)
						$this.animate({opacity: 1}, 450);
				}; 
				
				
				if (a && !settings.loading) {
					$this.animate({opacity: 0}, 450, pFilter);
				} else {
					pFilter();
				}

			},
			settings: function(){
				
				$pages = $this.find("." + settings.pagesClass);
				$pages.css("height", "");
				if ($pages.length != 0) {
					$$.stopCycle();
					$$.startCycle();
				}
			}
		};
	
	
		var options = {};
		var method = "start";

		if (arguments.length == 1 && typeof arguments[0] === 'string' ) {
			method = arguments[0];
		} else if (arguments.length == 1 && typeof arguments[0] === 'object' ) {
			options = arguments[0];
		} else if (arguments.length == 2 && typeof arguments[0] === 'string' && typeof arguments[1] === 'object' ) {
			method = arguments[0];
			options = arguments[1];
		} 
		return this.each(function() {        
			// If the settings have been saved and options are not passed
			if ($(this).data("settings") && typeof $(this).data("settings") === 'object'){
				$.extend( settings, $(this).data("settings") );
			}
			
			// If options exist, lets merge them
			// with our default settings
			if ( options ) { 
				$.extend( settings, options );
			}

			public.init.apply(this, arguments);
				
			// Method calling logic
			if ( public[method] ) {
				return public[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
			} else if ( typeof method === 'object' || ! method ) {
				return public.start.apply( this, arguments );
			} else {
				$.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
			}    
	
		});
	};
	
})(jQuery);

