/*
 * Generic Javascript Paging Functionality.
 * Takes a UL, counts the children and the pages accordlingly.
 * 
 * @author Keith Foster
 */
if(!tvh) var tvh = {};
tvh.Pager = (function(){
	/**
	 * Exclusively Private Objects
	 */
	var mode = 'js';				// this is either 0
	var properties = null; 			// array of all the properties
	var container = null; 			// html element, UL, that we'll add the property listings to.
	var paging_bars = null;			// html elements for the paging bars
	var page_number = 0; 			// int to store the current page number, 0 based.
	var per_page = 5;				// int to store max per page
	var max_pagelisting = 5;		// int to store the max number of viewable pages in the page listing bar
	var page_count = null;			// number of pages
	var list_item_template = null;	// string of the template for each of the properties
	var page_item_template = null;	// string of the template for each of the properties
	var sort_criteria = null;		// sort criteria area | price | bedrooms
	var order = 1;					// order setting, ascending or descending.
	var measurement = null; 	
	
	/**
	 * Sets up the private variables and then calls the first build of the results page with the default parameters.
	 * @return void;
	 */
	function initialise(element, list){
		container = element;
		if(mode=='js'){
			properties = list;
			list_item_template = unescape(container.html());
		} else {
			properties = container.find('ul.paged-items li');
		}
		
		paging_bars = jQuery('ul.pages');
		page_item_template = unescape(paging_bars.html())
		
		get_initial_params();
		build_pages();
		
		build_listing();		
		bind_pagingbar();
	}
	
	/**
	 * The per_page, sort by & order might be saved from a previous view.
	 */
	function get_initial_params(){
		var page = window.location.hash.toString() != '' ? parseInt(window.location.hash.toString().substring(1)) : 0;
		
		var sel_displaycount = jQuery('select.display-count').get(0);
		var sel_sort = jQuery('#sort-by').get(0);
		var sel_order = jQuery('#order-by').get(0);
		
		per_page = parseInt(sel_displaycount.options[sel_displaycount.selectedIndex].value);
		if(mode=='js'){
			order = sel_order.options[sel_order.selectedIndex].value == 'asc' ? 1 : -1;
			sort_criteria = sel_sort.options[sel_sort.selectedIndex].value;
			sort_properties();			
		}		
		page_count = Math.ceil(properties.length/per_page);
		
		if(page_count < page) { page = 0; }
		page_number = page;
		
		if(window.location.toString().indexOf('?print')!=-1){
			per_page = properties.length;
		}
		jQuery('#search-count').html(properties.length);
		if(jQuery('select.units').length>0){
			var unit_select = jQuery('select.units').get(0);
			measurement = unit_select.options[unit_select.selectedIndex].value;
		}
	}
	
	/**
	 * Bind all events for the paging bar.
	 */
	function set_all_displaycounts(index) {
		jQuery('select.display-count').each(function(){
			this.selectedIndex = index;
		});
	}
	function bind_pagingbar(){
		jQuery('select.display-count').change(function(){
			per_page = parseInt(this.options[this.selectedIndex].value);
			set_all_displaycounts(this.selectedIndex);
			page_number = 0;
			page_count = Math.ceil(properties.length/per_page);
			build_pages();
			build_listing();
			return false;
		});
		jQuery('#sort-by').change(function(){
			sort_criteria = this.options[this.selectedIndex].value;
			sort_properties();
			build_listing();
			return false;
		});
		jQuery('#order-by').change(function(){
			order = this.options[this.selectedIndex].value == 'asc' ? 1 : -1;
			sort_properties();
			build_listing();
			return false;
		});
		jQuery('select.units').change(function(){
			var decimal_points = 0;
			var ratio = this.options[this.selectedIndex].value;
			var label = 'ft';
			if(ratio < 1) {
				label = 'm';
				decimal_points = 2;
			}
			jQuery('span.area').each(function(){
				this.innerHTML = Math.round((parseFloat(this.innerHTML.replace(',', ''))*ratio)*Math.pow(10, decimal_points))/Math.pow(10, decimal_points);
			});
			jQuery('span.unit').each(function(){
				this.innerHTML = label;
			});
		});
	}
	
	/**
	 * Builds the pages list in the paging bar... that allows people to choose
	 * @return void
	 */
	
	function build_pages(){
		/* create local copies of global variables to reduce scope lookups - not sure if this will actually do anything for performance */		
		var start = page_number, end = null, ellipseAfter = false, ellipseBefore = false, deviation = 1, css_class = '', output = '';
		output += '<li><a href="#" class="prev">&laquo;</a></li><li class="'+((page_number == 0)?'active':'')+'"><a href="#">1</a></li>';
		var pageRangeLength = deviation*2+1;
		
		if(start<pageRangeLength) {
			start = 2;
		 	end = start + pageRangeLength;
			if(end == (pageRangeLength+1)) {
				end += deviation;
			}
			if(end > page_count) {
				end = page_count;
			} else {
				ellipseBefore = true;
			}
		} else if ((start+pageRangeLength) >= page_count) {
			start = page_count - (pageRangeLength - 1);
			end = page_count;
			ellipseAfter = true;
		} else {
			var pageInc = page_number + 1;
			var deviationInc = deviation + 1;
			
			start = pageInc - deviation;			
			end = pageInc + deviationInc;
			
			ellipseAfter = true;
			ellipseBefore = true;
		}
		
		if (ellipseAfter) { output += '<li>&hellip;</li>'; }
		for(var i=start; i<end; i++) {
			if((i-1)==page_number) { css_class += ' active'; }
			output += tvh.string_format(page_item_template, [ i, css_class ]);
			css_class = '';
		}
		if(ellipseBefore) { output += '<li>&hellip;</li>'; }
		
		if(page_count!=1) {
			output += '<li class="'+((page_number+1 == page_count)?'active':'')+'"><a href="#">'+page_count+'</a></li>';
		}
		output += '<li><a class="next" href="#">&raquo;</a></li>';
		paging_bars.html(output);
		paging_bars.css('display', 'block');
		bind_pages();
	}
	
	/**
	 * Binds the events to load the next pages.
	 * Click event, fires sets the page number to the innerHTML of the element then rebuilds the listing.
	 * Set visual idenifers that new page is selected;
	 * @return void
	 */
	function bind_pages(){
		var page_buttons = paging_bars.find('a');
		page_buttons.click(function(){
			var innerHTML = jQuery.trim(this.innerHTML);
			if(this.className=='prev' || this.className=='next') {
				if(this.className=='prev') {
					if(page_number == 0) return false;
					else page_number--;
				} else {
					if(page_number+1 == page_count) return false;
					else page_number++;
				}
			} else {
				page_number = parseInt(this.innerHTML)-1;
			}
			window.location.hash = page_number;
			build_pages();
			build_listing();
			set_active_pages();
			return false;
		});
	}
	
	/**
	 * Sets the visual identifiers so you know what page you're on.
	 * @return void
	 */
	function set_active_pages(){
		paging_bars.find('li').each(function(){
			var li = jQuery(this);
			li.removeClass('active');
			if( (parseInt(li.find('a').html())-1) == page_number) {
				li.addClass('active');
			}
		});		
	}
	
	/**
	 * Creates a string of html then sets the html to be the html of the container
	 * @return void
	 */
	function build_listing(){
		var total = properties.length;
		var n = ((page_number * per_page) + per_page);
		n = n <= total ? n : total;
		if (mode == 'js') {
			
		}
		else {
			for(var i=0; i<properties.length; i++) {
				properties[i].style.display = 'none';
			}
			
			for (var i = (page_number * per_page); i < n; i++) {
				properties[i].style.display = 'block';
			}
			
		}
		
	}
	
	/**
	 * Public Methods & Variables.
	 */
	return function(container, list){
		if(container.length == 0) {					// if the containing element is not found then just exit.
			return;
		}
		this.set_mode = function(value){
			mode = value;
		}
		if (list) {
			this.set_mode('js');
		} else {
			this.set_mode('html')
		}
		
		initialise(container, list);
	}
})();

