/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 1999-2017 CardContact Software & System Consulting
 * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
 *  ---------
 *
 *  This file is part of OpenSCDP.
 *
 *  OpenSCDP is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  OpenSCDP is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenSCDP; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @fileoverview A pagination generator
 */



/**
 * @param {Number} windowsize the number of pages to display
 */
function Paginator(windowsize, pageSize) {

	if (windowsize) {
		this.windowsize = windowsize;
	} else {
		this.windowsize = 10;
	}

	if (pageSize) {
		this.pageSize = pageSize;
	} else {
		this.pageSize = 20;
	}

	this.offset = 0;
}

exports.Paginator = Paginator;



/**
 * Calculate the current offset
 * based on the number of elements
 * and the current page size
 */
Paginator.prototype.getOffset = function(length) {
	if ((this.offset + this.pageSize >= length) || this.offset < 0) {
		// Set the offset to the first element of the last page
		var lastPageOffset = Math.floor((length - 1) / this.pageSize) * this.pageSize;

		if (lastPageOffset < 0) {
			lastPageOffset = 0;
		}

		return lastPageOffset;
	}

	return this.offset;
}



Paginator.prototype.setOffset = function(offset) {
	this.offset = offset;
}



Paginator.prototype.setPageSize = function(pageSize) {
	this.pageSize = pageSize;
}



Paginator.prototype.calculateOffsets = function(length) {
	GPSystem.log(GPSystem.DEBUG, module.id, "calculateOffsets( length=" + length + ")");
	var offsets = {};

	offsets.currentpage = Math.floor(this.getOffset(length) / this.pageSize);

	offsets.totalpages = Math.ceil(length / this.pageSize);
	offsets.firstpage = Math.max(offsets.currentpage - 2, 0);

	offsets.pages = offsets.totalpages - offsets.firstpage;
	if (offsets.pages > this.windowsize) {
		offsets.pages = this.windowsize;
	} else {
		// Make sure we do not shorten the list at the end
		p = offsets.totalpages - this.windowsize;
		if (p < 0) {
			p = 0;
		}
		if (p < offsets.firstpage) {
			offsets.firstpage = p;
			offsets.pages = offsets.totalpages - offsets.firstpage;
		}
	}

	offsets.previous = (offsets.currentpage - 1) * this.pageSize;
	offsets.next = (offsets.currentpage + 1) * this.pageSize;
	offsets.last = -1;

	offsets.window = [];
	for (var i = 0; i < offsets.pages; i++) {
		offsets.window[i] = (offsets.firstpage + i) * this.pageSize;
	}

	return offsets;
}



/**
 * Generate a page navigator
 *
 * @param {Number} currentOffset the current element offset
 * @param {Number} length the total number of elements
 * @param {Number} pageSize the number of elements per page
 *
 * @returns the pagination element
 * @type XML
 */
Paginator.prototype.getPagination = function(length, urlprefix) {
	default xml namespace = "http://www.w3.org/1999/xhtml";
	var nav = <ul class="pagination"/>;

	var offsets = this.calculateOffsets(length);

	if (offsets.totalpages == 1) {
		return nav;
	}

	// Navigate backwards
	if (offsets.currentpage > 0) {
		var url = urlprefix + "offset=" + offsets.previous;
		var prevPageSign = String.fromCharCode(0xAB);
		var li =
			<li>
				<a href={url}>{prevPageSign}</a>
			</li>
		nav.appendChild(li);
	}

	// Back to first page
	if (offsets.firstpage > 0) {
		var url = urlprefix + "offset=0";
		var li =
			<li>
				<a href={url}>1</a>
			</li>
		nav.appendChild(li);
	}

	if (offsets.firstpage > 1) {
	      nav.appendChild(<li>...</li>);
	}

	// Page links
	for (var i = 0; i < offsets.window.length; i++) {
		if (offsets.firstpage + i == offsets.currentpage) {
			nav.appendChild(<li class="active">{offsets.firstpage + i + 1}</li>);
		} else {
			var url = urlprefix + "offset=" + offsets.window[i];
			var li =
				<li>
					<a href={url}>{offsets.firstpage + i + 1}</a>
				</li>;
			nav.appendChild(li);
		}
	}

	// More to follow
	if (offsets.firstpage + offsets.pages < offsets.totalpages - 1) {
		nav.appendChild(<li>...</li>);
	}
	if (offsets.firstpage + offsets.pages < offsets.totalpages) {
		var url = urlprefix + "offset=" + offsets.last;
		var li =
			<li>
				<a href={url}>{offsets.totalpages}</a>
			</li>;
		nav.appendChild(li);
	}

	// Navigate forward
	if ((offsets.currentpage + 1) < offsets.totalpages) {
		var url = urlprefix + "offset=" + offsets.next;
		var nextPageSign = String.fromCharCode(0xBB);
		var li =
			<li>
				<a href={url}>{nextPageSign}</a>
			</li>
		nav.appendChild(li);
	}

	return <div>{nav}</div>;
}



/**
 * Generate a page navigator
 *
 * @param {Number} start the current element offset
 * @param {Number} length the total number of elements
 * @param {Number} pageSize the number of elements per page
 *
 * @returns the pagination element
 * @type XML
 */
Paginator.prototype.getPaginationStyle2 = function(length, urlprefix) {
	default xml namespace = "http://www.w3.org/1999/xhtml";
	var nav = <div/>;

	var offsets = this.calculateOffsets(length);

	// Back to first page
	if (offsets.firstpage > 0) {
		var url = urlprefix + "offset=0";
		nav.appendChild(<a href={url}>1</a>);
	}

	if (offsets.firstpage > 1) {
		nav.appendChild(" ... ");
	} else if (offsets.firstpage == 1) {
		nav.appendChild(" | ");
	}

	// Page links
	for (var i = 0; i < offsets.window.length; i++) {
		if (offsets.firstpage + i == offsets.currentpage) {
			nav.appendChild(<em>{offsets.firstpage + i + 1}</em>);
		} else {
			var url = urlprefix + "offset=" + offsets.window[i];
			nav.appendChild(<a href={url}>{offsets.firstpage + i + 1}</a>);
		}
		if (i < offsets.pages - 1) {
			nav.appendChild(" | ");
		}
	}

	// More to follow
	var url = urlprefix + "offset=" + offsets.last;
	var lastPage = <a href={url}>{offsets.totalpages}</a>;
	if (offsets.firstpage + offsets.pages < offsets.totalpages - 1) {
		nav.appendChild(" ... ");
		nav.appendChild(lastPage);
	} else if (offsets.firstpage + offsets.pages < offsets.totalpages) {
		nav.appendChild(" | ");
		nav.appendChild(lastPage);
	}

	// Navigate backwards
	if (offsets.currentpage > 0) {
		var url = urlprefix + "offset=" + offsets.previous;
		var nextPageSign = String.fromCharCode(0xAB);
		nav.appendChild(<a href={url}>{nextPageSign}</a>);
	}

	// Navigate forward
	if ((offsets.currentpage + 1) < offsets.totalpages) {
		var url = urlprefix + "offset=" + offsets.next;
		var nextPageSign = String.fromCharCode(0xBB);
		nav.appendChild(<a href={url}>{nextPageSign}</a>);
	}

	return nav;
}
