(function($) {
	var defaults = {
			'count': 0,
			'current': null,
			'page': 1,
			'render_pages': 10,
			'per_page': 10,
            'prev_button': '<a href="#" class="button margin-right">«</a>',
            'next_button': '<a href="#" class="button">»</a>',
			'next': function() {},
			'prev': function() {},
			'click': function() {},
			'change': function() {},
			'init': function() {}
	};

	jQuery.fn.paginate = function(opt) {
		opt = $.extend({}, defaults, opt);

		this.each(function() {
			$(this).empty();

			var sender = this;
			var firstPage = 1;
			var renderPages = opt['render_pages'];
			var count = opt['count'];
			var perPage = opt['per_page'];
			var lastPage = Math.ceil(count / perPage);
			var currentPage = opt['page'];

			// calc where we are
			if(opt['current']) {
				var currentPage = Math.floor(opt['current'] / perPage) + 1;
				opt['current'] = null;
			}

			var initCallback = opt['init'];
			opt['init'] = null;

			if(initCallback && initCallback(opt) == false) {
				return;
			}
			
			// Nothing to do
			if(count == 0) {
				return;
			}
			
			var changeCallback = function(newOpt) {				
				if(opt['change'](newOpt, this) != false) {
					$(sender).paginate(newOpt);
				}

				return false;
			};
			
			var clickCallback = function() {
				var newOpt = opt;
				newOpt['page'] = Math.min(lastPage, this.id);
				
				if(opt['click'](newOpt, this) != false) {
					changeCallback(newOpt);
				}
				
				return false;
			};

			var prevCallback = function() {
				var newOpt = opt;
				newOpt['page'] = Math.max(firstPage, currentPage - 1);

				if(opt['prev'](newOpt, this) != false) {
					changeCallback(newOpt);
				}
				
				return false;
			};

			var nextCallback = function() {
				var newOpt = opt;
				newOpt['page'] = Math.min(lastPage, currentPage + 1);
				
				if(opt['next'](newOpt, this) != false) {
					changeCallback(newOpt);
				}

				return false;
			};

			// The center of rendered pages - the current one
			var centerPage = Math.ceil((renderPages - 1) / 2);

			var renderStart = Math.max(firstPage, currentPage - centerPage);
			var renderEnd = Math.min(lastPage, renderStart + renderPages - 1);

			// We are at the end and need to prepend some pages to fill
			pageFill = renderPages - ((renderEnd - renderStart) + 1);

			if(pageFill < renderPages) {
				renderStart = renderStart - pageFill;
			} else {
				renderStart -= pageFill;
			}

			// not go negative
			renderStart = Math.max(firstPage, renderStart);

			$(this).append(
				$(opt['prev_button']).click(prevCallback)
			);
			
			var node = null;

			for(var renderPage = renderStart; renderPage <= renderEnd; renderPage++) {
				node = $('<a></a>').addClass('page-button').append(renderPage).attr('href', '#').click(clickCallback).attr('id', renderPage);
				
				if(renderPage == currentPage) {
					node.addClass('current-page');
				}
				
				$(this).append(node);	
			}

			$('a.page-button:last').addClass('margin-right');

			$(this).append(
				$(opt['next_button']).click(nextCallback)
			);

			return this;
		});
	};

})(jQuery);
