// NOTE: The funtion paginate needs the function sprintf from stringFunction.js

/**
 * Creates page links for insertion into a template, suitable for pagination of 
 * generic pages.
 *
 * The generated page links are returned as a string and cover all pages within
 * currentPage +- range. If the links would get out of bounds on one side, the
 * other side is extended (if possible), so that 2*range+1 page links are
 * displayed.
 *
 * If the current page is not the first page, a back arrow (previos page) is
 * generated, similarly, if the current page is not the last page, a forward
 * arrow (next page) is generated.
 *
 * If the first page is not within the displayed range, a double back arrow
 * (first page) link is generated. If the last page is not within the displayed
 * range, a double forward arrow (last page) link is generated.
 *
 * @param currentPage The number of the current page.
 * @param totalPages The total number of valid pages.
 * @param range The number of pages before and after the current one that
 *               shall have direct links shown.
 * @param urlFnc A callback function that accepts a parameter for the
 *               page number, a parameter to determine the host under which
 *               the script is running and generates an url poiting to that page.
 * @param host   The host under which the script is running.
 * @param graphical Set the switches to buttons (true) instead of ordinary links
 *                  (false).
 *
 * @return A string containing the generated page links.
 */
function paginate(currentPage, totalPages, range, urlFnc, host, graphical)
{
	// Just a safety net, if user input gets passed here unfiltered
	currentPage = parseInt(currentPage);
	totalPages = parseInt(totalPages);
	range = parseInt(range);

	var startpage = Math.max(1, currentPage - range);
	var endpage = Math.min(totalPages, currentPage + range);

	// Adjust the start and end to cover 2*range+1 pages, if possible
	if (endpage - startpage < 2 * range)
	{
		startpage = Math.max(1, endpage - 2 * range);
		endpage = Math.min(totalPages, startpage + 2 * range);
	}

	if (graphical)
	{
		var linkTpl = '<a href="%s" class="pagination_link">' +
			'<span class="%s">%s</span></a>';
		var currentTpl =
			'<span class="pagination_link"><span class="%s">%s</span></span>';
	}
	else
		var linkTpl = '<a href="%s">%s</a>';

	var pageLinks = new Array();

	// Back arrow and back to page 1 arrow
	if (startpage > 1)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(1, host), 'bigButtonActive',
				'erste Seite'));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(1, host), '&lt;&lt;'));
	}

	if (currentPage > 1)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(currentPage - 1, host),
				'smallButtonActive', '&lt;&lt;'));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(currentPage - 1, host),
				'&lt;'));
	}

	// The accessible page range
	for (i = startpage; i < currentPage; i++)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(i, host),
				i < 100 ? 'smallButtonActive' : 'mediumButtonActive', i));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(i, host), i));
	}

	if (graphical)
		pageLinks.push(sprintf(currentTpl,
			currentPage < 100 ? 'smallButtonInactive' : 'mediumButtonInactive',
			currentPage));
	else
		pageLinks.push(currentPage);

	for (i = currentPage; i < endpage; i++)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(i + 1, host),
				(i + 1) < 100 ? 'smallButtonActive' : 'mediumButtonActive',
				i + 1));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(i + 1, host), i + 1));
	}

	// Forward arrow and forward to last page arrow
	if (currentPage < totalPages)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(currentPage + 1, host),
				'smallButtonActive', '&gt;&gt;'));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(currentPage + 1, host),
				'&gt;'));
	}

	if (totalPages > endpage)
	{
		if (graphical)
			pageLinks.push(sprintf(linkTpl, urlFnc(totalPages, host),
				'bigButtonActive', 'letzte Seite'));
		else
			pageLinks.push(sprintf(linkTpl, urlFnc(totalPages, host),
				'&gt;&gt;'));
	}

	return pageLinks.join(' ');
}

