/**
 * jquery.limePaginate
 * 
 * Copyright (c) 2009 Christopher Pietsch
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Date: 2009-06-03 07:16:50 +0000 (Wed, 03 Jun 2009)
 * Revision: 1870 
 */
 
(function($) {
	
	$.fn.addActiveClass = function(current,target) {
		if(current==target) { return this.addClass('active'); }
		else {return this;}
	}
	
	// static constructs
	$.tools = $.tools || {version: {}};
	
	$.tools.version.limePaginate = '0.1';
	
	var current = null;
	
	// constructor
	function limePaginate(root, conf) {   

		// current instance
		var self = this;  
		if (!current) { current = self; }		
		
		// generic binding function
		function bind(name, fn) {
			$(self).bind(name, function(e, args)  {
				if (fn && fn.call(this, args.index) === false && args) {
					args.proceed = false;	
				}	
			});	
			
			return self;
		}
		
		// bind all callbacks from configuration
		$.each(conf, function(name, fn) {
			if ($.isFunction(fn)) { bind(name, fn); }
		});   
		
		
		var index = 0;
		var id=$(root).attr('id');
		var ajaxData=null;
		var template=null;
		
		function find(query, ctx) {
			return query.indexOf("#") != -1 ? $(query).eq(0) : ctx.siblings(query).eq(0);	
		}
		
		// get handle to navigational elements
		var $pager = $(conf.pager, root);
		//console.log($pager);
		var $items = $(conf.items, root);
		var $nextPage = $(conf.nextPage,root);
		var $prevPage = $(conf.prevPage,root);
		/*
		var navi = find(conf.navi, root);
		var prev = find(conf.prev, root);
		var next = find(conf.next, root);
		var prevPage = find(conf.prevPage, root);
		var nextPage = find(conf.nextPage, root);
		*/
		
		// methods
		$.extend(self, {
			getIndex: function() {
				return index;	
			},
			getPageIndex: function() {
				return Math.ceil(index / conf.itemsPerPage);	
			},
			getSize: function() {
				if(conf.ajax){
					return ajaxData.length;
				} else {
				//	console.log(self.getItems())
					return self.getItems().size();
				}
			},
			getSizeStart: function() {
				var itemsStart = ( (this.getIndex()+1) * conf.itemsPerPage ) - conf.itemsPerPage;
				return itemsStart + 1;
			},
			getSizeEnd: function() {
				var itemsEnd = (this.getIndex()+1) * conf.itemsPerPage;
				if ( itemsEnd > this.getSize() ) var itemsEnd = this.getSize();
				return itemsEnd;	
			},
			getPagerSize: function(){
				return Math.ceil(this.getSize()/conf.itemsPerPage);
			},
			getItems: function() {
				return $items;
			},
			getPager: function() {
				return $pager;
			},
			getItemsPerPage: function(page){
				return $items.slice(this.getIndex() * conf.itemsPerPage,(this.getIndex() + 1) * conf.itemsPerPage);
			},
			nextPage: function(fn) {
				return this.setPage(this.getIndex() + 1, fn);
			},
			prevPage: function(fn) {
				return this.setPage(this.getIndex() - 1, fn);
			},
			setPage: function(page, fn) {
				//console.log(this.getSize());
				index=page;
				if(conf.ajax){
					this.repaginateAjax(page, fn);
				} else {
					this.repaginateNormal(page, fn);
				}
				//console.log()
				this.buildPager();
				if($.isFunction(conf.afterPaginate)){
					conf.afterPaginate(self);
				}
			},
			getCleanUrl: function(){
				return document.location.toString().split('#')[0];
			},
			buildPager: function(fn){
				var lastPage=0;
				
				//empty the pager
				$pager.find(conf.pagerLinks).empty();
				
				//set up the range of pagerlinks around the active page
				var pageStart = (this.getIndex() - conf.pagerNumDisplay);
				var pageEnd = (this.getIndex() + conf.pagerNumDisplay);				
				if(pageStart<0){pageEnd=pageEnd+(-1*pageStart);}
				if(pageEnd>this.getPagerSize()-1){pageStart=pageStart-(-1*((this.getPagerSize()-1)-pageEnd))}
				
				//build the pager
				for (var page = 0; page < this.getPagerSize(); page++)
				{
					if(page==0 || page == this.getPagerSize()-1 || ((page >= pageStart) && (page <= pageEnd))){
						
						if((page-lastPage)>1){ $(conf.pagerDotText).appendTo($(conf.pagerLinks,$pager)); }
					
						var pagerItem = ($.isFunction(conf.pagerAnchorBuilder))
							? conf.pagerAnchorBuilder(page, id)
							: '<span class="page"><a href="'+self.getCleanUrl()+'#page-'+(page+1)+'">' + (page + 1) + '</a></span>';
						if (!pagerItem)
							return;
						var $pagerItem = $(pagerItem);
						$pagerItem
						.bind('click', {'newPage': page}, function(event) {
							//self.setPage(event.data['newPage'],fn);
							var hash = $('a',this).attr('href').replace(/^.*#/, '');
							$.historyLoad(hash);
							return false;
						})
						.addActiveClass(page,this.getIndex())
						.appendTo($(conf.pagerLinks,$pager))
						lastPage=page;
						
						//console.log("ahah");
					}
				}
				
				// prev buttons disabled flag
				if (this.getIndex() === 0) {
					$prevPage.addClass(conf.disabledClass);					
				} else {
					$prevPage
					.removeClass(conf.disabledClass)
					.find("a").attr("href",self.getCleanUrl()+"#page-"+(this.getIndex()));
				}

				// next buttons disabled flag
				if (this.getIndex() >= this.getPagerSize()-1) {
					$nextPage.addClass(conf.disabledClass);
				} else {
					$nextPage
					.removeClass(conf.disabledClass)
					.find("a").attr("href",self.getCleanUrl()+"#page-"+(this.getIndex()+2));
				}
				
				//current Page
				if(conf.pagerCurrentPage){
					$(conf.pagerCurrentPage,root).html(this.getIndex()+1);
				
				}
				
				//current Entry Start
				if(conf.pagerCurrentEntryStart){
					$(conf.pagerCurrentEntryStart,root).html( this.getSizeStart() );
				}
				//current Entry Start
				if(conf.pagerCurrentEntryEnd){
					$(conf.pagerCurrentEntryEnd,root).html( this.getSizeEnd() );
				}
				
				//total Entries
				if(conf.pagerTotalEntries){
					$(conf.pagerTotalEntries,root).html(this.getSize());
				}
				//total Pages
				if(conf.pagerTotalPages){
					$(conf.pagerTotalPages,root).html(this.getPagerSize());
				}
				
			},
			repaginateNormal: function(i, fn) {
 
				/* Fehler abfangen
				var maxPage=this.getPagerSize();
				if(i>=maxPage){	i=maxPage-1; }
				if(i<0){ i=0; } */
				
				// Show or Hide
			
				this.getItems()
				.hide()
				.slice(this.getIndex() * conf.itemsPerPage,(this.getIndex() + 1) * conf.itemsPerPage).show()
								
				return self; 
			},
			repaginateAjax: function(i, fn) {
 				$(conf.itemBox,root).empty();
				
				var test = $(ajaxData).slice(this.getIndex() * conf.itemsPerPage,(this.getIndex() + 1) * conf.itemsPerPage)
								
				test.each(function(i,item){
					$(conf.itemBox,root).append(self.replaceTemplateVariables(template, item, ""));				
			    });
							
				return self; 
			},
			initialiseAjax: function(callback){
				template=$(conf.ajax.template, root).html();
				
				$.getJSON(conf.ajax.url, conf.ajax.params,
					function(data){
						ajaxData=data;
						callback();
			 	});
			},
			_history: function(hash,fn) {
				
				var page=0;
				//console.log(hash);
				if(conf.pagerAnchorJump){
					window.scroll(0,0);
				}
				
				if(hash) {
					var argv = hash.split("-");
					switch(argv[0]) {
						case "page":
							self.setPage(hash.split("-")[1]-1);
						break;
						default:
							self.setPage(conf.startPage);							
						break;
					}
				} else {
					self.setPage(conf.startPage);
				}				
			},
			replaceTemplateVariables : function(template, jsonBranch, currentPosition) {
				for(var node in jsonBranch) {
					var regex = new RegExp("%" + currentPosition + node + "%", "g");
					template = template.replace(regex, jsonBranch[node]);
					if(typeof jsonBranch[node] == 'object')
					template = self.replaceTemplateVariables(template, jsonBranch[node], currentPosition + node + ".")
				}
				return template;
			}
		});
		
		if(conf.ajax){
			self.initialiseAjax(function(){ $.historyInit(self._history) });
		} else {
			$.historyInit(self._history, self.getCleanUrl());
		}
		
		if(self.getSize()>conf.itemsPerPage){
			$pager.removeClass('hidden');
		}
		
		$nextPage.add($prevPage).click(function(){
			var hash = $('a',this).attr('href').replace(/^.*#/, '');
			$.historyLoad(hash);
			return false;
		})

	}	
		
	// jQuery plugin implementation
	$.fn.limePaginate = function(conf) { 
			
		// already constructed --> return API
		var el = this.eq(typeof conf == 'number' ? conf : 0).data("limePaginate");
		if (el) { return el; }		
		
 
		var opts = {
			
			// basics
			startPage: 0,
			pagerNumDisplay: 2,
			pagerDotText:"<span>...</span>",
			itemsPerPage: 2,
			
			lastPage:0,
			pager:'.paginationBox',
			items:'.teaserBox',
			itemBox: '.itemsBox',
			api:false,
			disabledClass: 'disabled',
			nextPage:'.next',
			prevPage:'.prev',
			pagerLinks: '.pages',
			
			pagerCurrentPage: '.currentPage',
			pagerTotalPages:'.totalPages',
			
			pagerCurrentEntryStart: '.currentEntryStart',
			pagerCurrentEntryEnd: '.currentEntryEnd',
			pagerTotalEntries: '.totalEntries',
			
			pagerAnchorBuilder:null,
			pagerAnchorJump:true,
			
			afterPaginate: function($self){
/* FIRST LAST CHILD ITEMS								$self.getItems().removeClass("firstChild").removeClass("lastChild");
				$activeItems= $self.getItemsPerPage(null);
				$activeItems.eq(0).addClass("firstChild");
				$activeItems.eq($activeItems.length-1).addClass("lastChild");
				
			*/
				// LAST FIRSTCHILD PAGER
				$('.pages',$self.getPager()).each(function(){
					$pagerChilds = $(this).children();
					$pagerChilds.eq(0).addClass("firstChild");
					//console.log($pagerChilds);
					$pagerChilds.eq($pagerChilds.length-1).addClass("lastChild");
				$pagerChilds.removeClass("beforeDots").removeClass("afterDots");
				})
				
				$dots= $(".dots",$self.getPager());
				if($dots[0]){
					$dots.prev().addClass("beforeDots");
					$dots.next().addClass("afterDots");
				}/**/
			}
		}; 
	
		
		$.extend(opts, conf);		
		
		this.each(function() {			
			el = new limePaginate($(this), opts);
			$(this).data("limePaginate", el);	
		});
		
		return opts.api ? el: this; 
		
	};
			
	
})(jQuery);