/*
 * Copyright 2012 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.wicket.panels;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;

import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.BasePage;

public class PagerPanel extends Panel {

	private static final long serialVersionUID = 1L;

	public PagerPanel(String wicketId, final int currentPage, final int totalPages,
			final Class<? extends BasePage> pageClass, final PageParameters baseParams) {
		super(wicketId);
		List<PageObject> pages = new ArrayList<PageObject>();
		int[] deltas;
		if (currentPage == 1) {
			// [1], 2, 3, 4, 5
			deltas = new int[] { 0, 1, 2, 3, 4 };
		} else if (currentPage == 2) {
			// 1, [2], 3, 4, 5
			deltas = new int[] { -1, 0, 1, 2, 3 };
		} else {
			// 1, 2, [3], 4, 5
			deltas = new int[] { -2, -1, 0, 1, 2 };
		}

		if (totalPages > 0) {
			pages.add(new PageObject("\u2190", currentPage - 1));
		}
		for (int delta : deltas) {
			int page = currentPage + delta;
			if (page > 0 && page <= totalPages) {
				pages.add(new PageObject("" + page, page));
			}
		}
		if (totalPages > 0) {
			pages.add(new PageObject("\u2192", currentPage + 1));
		}

		ListDataProvider<PageObject> pagesProvider = new ListDataProvider<PageObject>(pages);
		final DataView<PageObject> pagesView = new DataView<PageObject>("page", pagesProvider) {
			private static final long serialVersionUID = 1L;

			@Override
			public void populateItem(final Item<PageObject> item) {
				PageObject pageItem = item.getModelObject();
				PageParameters pageParams = new PageParameters(baseParams);
				pageParams.put("pg", pageItem.page);
				LinkPanel link = new LinkPanel("pageLink", null, pageItem.text, pageClass, pageParams);
				link.setRenderBodyOnly(true);
				item.add(link);
				if (pageItem.page == currentPage || pageItem.page < 1 || pageItem.page > totalPages) {
					WicketUtils.setCssClass(item, "disabled");
				}
			}
		};
		add(pagesView);
	}

	private class PageObject implements Serializable {

		private static final long serialVersionUID = 1L;

		String text;
		int page;

		PageObject(String text, int page) {
			this.text = text;
			this.page = page;
		}
	}
}
