/*
 * Copyright 2011 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.pages;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.wicket.MarkupContainer;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebResponse;

import com.gitblit.Constants;
import com.gitblit.Constants.AuthenticationType;
import com.gitblit.Keys;
import com.gitblit.extensions.NavLinkExtension;
import com.gitblit.extensions.UserMenuExtension;
import com.gitblit.models.Menu.ExternalLinkMenuItem;
import com.gitblit.models.Menu.MenuDivider;
import com.gitblit.models.Menu.MenuItem;
import com.gitblit.models.Menu.PageLinkMenuItem;
import com.gitblit.models.Menu.ParameterMenuItem;
import com.gitblit.models.Menu.ToggleMenuItem;
import com.gitblit.models.NavLink;
import com.gitblit.models.NavLink.PageNavLink;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ModelUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.NonTrimmedPasswordTextField;
import com.gitblit.wicket.SessionlessForm;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.AvatarImage;
import com.gitblit.wicket.panels.LinkPanel;
import com.gitblit.wicket.panels.NavigationPanel;

/**
 * Root page is a topbar, navigable page like Repositories, Users, or
 * Federation.
 *
 * @author James Moger
 *
 */
public abstract class RootPage extends BasePage {

	boolean showAdmin;

	IModel<String> username = new Model<String>("");
	IModel<String> password = new Model<String>("");
	List<RepositoryModel> repositoryModels = new ArrayList<RepositoryModel>();

	public RootPage() {
		super();
	}

	public RootPage(PageParameters params) {
		super(params);
	}

	@Override
	protected void setupPage(String repositoryName, String pageName) {

		// CSS header overrides
		add(new HeaderContributor(new IHeaderContributor() {
			private static final long serialVersionUID = 1L;

			@Override
			public void renderHead(IHeaderResponse response) {
				StringBuilder buffer = new StringBuilder();
				buffer.append("<style type=\"text/css\">\n");
				buffer.append(".navbar-inner {\n");
				final String headerBackground = app().settings().getString(Keys.web.headerBackgroundColor, null);
				if (!StringUtils.isEmpty(headerBackground)) {
					buffer.append(MessageFormat.format("background-color: {0};\n", headerBackground));
				}
				final String headerBorder = app().settings().getString(Keys.web.headerBorderColor, null);
				if (!StringUtils.isEmpty(headerBorder)) {
					buffer.append(MessageFormat.format("border-bottom: 1px solid {0} !important;\n", headerBorder));
				}
				buffer.append("}\n");
				final String headerBorderFocus = app().settings().getString(Keys.web.headerBorderFocusColor, null);
				if (!StringUtils.isEmpty(headerBorderFocus)) {
					buffer.append(".navbar ul li:focus, .navbar .active {\n");
					buffer.append(MessageFormat.format("border-bottom: 4px solid {0};\n", headerBorderFocus));
					buffer.append("}\n");
				}
				final String headerForeground = app().settings().getString(Keys.web.headerForegroundColor, null);
				if (!StringUtils.isEmpty(headerForeground)) {
					buffer.append(".navbar ul.nav li a {\n");
					buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
					buffer.append("}\n");
					buffer.append(".navbar ul.nav .active a {\n");
					buffer.append(MessageFormat.format("color: {0};\n", headerForeground));
					buffer.append("}\n");
				}
				final String headerHover = app().settings().getString(Keys.web.headerHoverColor, null);
				if (!StringUtils.isEmpty(headerHover)) {
					buffer.append(".navbar ul.nav li a:hover {\n");
					buffer.append(MessageFormat.format("color: {0} !important;\n", headerHover));
					buffer.append("}\n");
				}
				buffer.append("</style>\n");
				response.renderString(buffer.toString());
				}
			}));

		boolean authenticateView = app().settings().getBoolean(Keys.web.authenticateViewPages, false);
		boolean authenticateAdmin = app().settings().getBoolean(Keys.web.authenticateAdminPages, true);
		boolean allowAdmin = app().settings().getBoolean(Keys.web.allowAdministration, true);
		boolean allowLucene = app().settings().getBoolean(Keys.web.allowLuceneIndexing, true);
		boolean displayUserPanel = app().settings().getBoolean(Keys.web.displayUserPanel, true);
		boolean isLoggedIn = GitBlitWebSession.get().isLoggedIn();

		if (authenticateAdmin) {
			showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
			// authentication requires state and session
			setStatelessHint(false);
		} else {
			showAdmin = allowAdmin;
			if (authenticateView) {
				// authentication requires state and session
				setStatelessHint(false);
			} else {
				// no authentication required, no state and no session required
				setStatelessHint(true);
			}
		}

		if (displayUserPanel && (authenticateView || authenticateAdmin)) {
			if (isLoggedIn) {
				UserMenu userFragment = new UserMenu("userPanel", "userMenuFragment", RootPage.this);
				add(userFragment);
			} else {
				LoginForm loginForm = new LoginForm("userPanel", "loginFormFragment", RootPage.this);
				add(loginForm);
			}
		} else {
			add(new Label("userPanel").setVisible(false));
		}

		// navigation links
		List<NavLink> navLinks = new ArrayList<NavLink>();
		if (!authenticateView || (authenticateView && isLoggedIn)) {
			UserModel user = UserModel.ANONYMOUS;
			if (isLoggedIn) {
				user = GitBlitWebSession.get().getUser();
			}

			navLinks.add(new PageNavLink(isLoggedIn ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class,
					getRootPageParameters()));
			if (isLoggedIn && app().tickets().isReady()) {
				navLinks.add(new PageNavLink("gb.myTickets", MyTicketsPage.class));
			}
			navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class,
					getRootPageParameters()));
			
			navLinks.add(new PageNavLink("gb.filestore", FilestorePage.class, getRootPageParameters()));
				
			navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters()));
			if (allowLucene) {
				navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class));
			}

			if (!authenticateView || (authenticateView && isLoggedIn)) {
				addDropDownMenus(navLinks);
			}

			// add nav link extensions
			List<NavLinkExtension> extensions = app().plugins().getExtensions(NavLinkExtension.class);
			for (NavLinkExtension ext : extensions) {
				navLinks.addAll(ext.getNavLinks(user));
			}
		}

		NavigationPanel navPanel = new NavigationPanel("navPanel", getRootNavPageClass(), navLinks);
		add(navPanel);

		// display an error message cached from a redirect
		String cachedMessage = GitBlitWebSession.get().clearErrorMessage();
		if (!StringUtils.isEmpty(cachedMessage)) {
			error(cachedMessage);
		} else if (showAdmin) {
			int pendingProposals = app().federation().getPendingFederationProposals().size();
			if (pendingProposals == 1) {
				info(getString("gb.OneProposalToReview"));
			} else if (pendingProposals > 1) {
				info(MessageFormat.format(getString("gb.nFederationProposalsToReview"),
						pendingProposals));
			}
		}

		super.setupPage(repositoryName, pageName);
	}

	protected Class<? extends BasePage> getRootNavPageClass() {
		return getClass();
	}

	private PageParameters getRootPageParameters() {
		if (reusePageParameters()) {
			PageParameters pp = getPageParameters();
			if (pp != null) {
				PageParameters params = new PageParameters(pp);
				// remove named project parameter
				params.remove("p");

				// remove named repository parameter
				params.remove("r");

				// remove named user parameter
				params.remove("user");

				// remove days back parameter if it is the default value
				if (params.containsKey("db")
						&& params.getInt("db") == app().settings().getInteger(Keys.web.activityDuration, 7)) {
					params.remove("db");
				}
				return params;
			}
		}
		return null;
	}

	protected boolean reusePageParameters() {
		return false;
	}

	private void loginUser(UserModel user) {
		if (user != null) {
			HttpServletRequest request = ((WebRequest) getRequest()).getHttpServletRequest();
			HttpServletResponse response = ((WebResponse) getResponse()).getHttpServletResponse();

			// Set the user into the session
			GitBlitWebSession session = GitBlitWebSession.get();

			// issue 62: fix session fixation vulnerability
			session.replaceSession();
			session.setUser(user);

			request = ((WebRequest) getRequest()).getHttpServletRequest();
			response = ((WebResponse) getResponse()).getHttpServletResponse();
			request.getSession().setAttribute(Constants.ATTRIB_AUTHTYPE, AuthenticationType.CREDENTIALS);

			// Set Cookie
			app().authentication().setCookie(request, response, user);

			if (!session.continueRequest()) {
				PageParameters params = getPageParameters();
				if (params == null) {
					// redirect to this page
					redirectTo(getClass());
				} else {
					// Strip username and password and redirect to this page
					params.remove("username");
					params.remove("password");
					redirectTo(getClass(), params);
				}
			}
		}
	}

	protected List<RepositoryModel> getRepositoryModels() {
		if (repositoryModels.isEmpty()) {
			final UserModel user = GitBlitWebSession.get().getUser();
			List<RepositoryModel> repositories = app().repositories().getRepositoryModels(user);
			repositoryModels.addAll(repositories);
			Collections.sort(repositoryModels);
		}
		return repositoryModels;
	}

	protected void addDropDownMenus(List<NavLink> navLinks) {

	}

	protected List<com.gitblit.models.Menu.MenuItem> getRepositoryFilterItems(PageParameters params) {
		final UserModel user = GitBlitWebSession.get().getUser();
		Set<MenuItem> filters = new LinkedHashSet<MenuItem>();
		List<RepositoryModel> repositories = getRepositoryModels();

		// accessible repositories by federation set
		Map<String, AtomicInteger> setMap = new HashMap<String, AtomicInteger>();
		for (RepositoryModel repository : repositories) {
			for (String set : repository.federationSets) {
				String key = set.toLowerCase();
				if (setMap.containsKey(key)) {
					setMap.get(key).incrementAndGet();
				} else {
					setMap.put(key, new AtomicInteger(1));
				}
			}
		}
		if (setMap.size() > 0) {
			List<String> sets = new ArrayList<String>(setMap.keySet());
			Collections.sort(sets);
			for (String set : sets) {
				filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", set,
						setMap.get(set).get()), "set", set, params));
			}
			// divider
			filters.add(new MenuDivider());
		}

		// user's team memberships
		if (user != null && user.teams.size() > 0) {
			List<TeamModel> teams = new ArrayList<TeamModel>(user.teams);
			Collections.sort(teams);
			for (TeamModel team : teams) {
				filters.add(new ToggleMenuItem(MessageFormat.format("{0} ({1})", team.name,
						team.repositories.size()), "team", team.name, params));
			}
			// divider
			filters.add(new MenuDivider());
		}

		// custom filters
		String customFilters = app().settings().getString(Keys.web.customFilters, null);
		if (!StringUtils.isEmpty(customFilters)) {
			boolean addedExpression = false;
			List<String> expressions = StringUtils.getStringsFromValue(customFilters, "!!!");
			for (String expression : expressions) {
				if (!StringUtils.isEmpty(expression)) {
					addedExpression = true;
					filters.add(new ToggleMenuItem(null, "x", expression, params));
				}
			}
			// if we added any custom expressions, add a divider
			if (addedExpression) {
				filters.add(new MenuDivider());
			}
		}
		return new ArrayList<MenuItem>(filters);
	}

	protected List<MenuItem> getTimeFilterItems(PageParameters params) {
		// days back choices - additive parameters
		int daysBack = app().settings().getInteger(Keys.web.activityDuration, 7);
		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);
		if (daysBack < 1) {
			daysBack = 7;
		}
		if (daysBack > maxDaysBack) {
			daysBack = maxDaysBack;
		}
		PageParameters clonedParams;
		if (params == null) {
			clonedParams = new PageParameters();
		} else {
			clonedParams = new PageParameters(params);
		}

		if (!clonedParams.containsKey("db")) {
			clonedParams.put("db",  daysBack);
		}

		List<MenuItem> items = new ArrayList<MenuItem>();
		Set<Integer> choicesSet = new TreeSet<Integer>(app().settings().getIntegers(Keys.web.activityDurationChoices));
		if (choicesSet.isEmpty()) {
			 choicesSet.addAll(Arrays.asList(1, 3, 7, 14, 21, 28));
		}
		List<Integer> choices = new ArrayList<Integer>(choicesSet);
		Collections.sort(choices);
		String lastDaysPattern = getString("gb.lastNDays");
		for (Integer db : choices) {
			if (db == 1) {
				items.add(new ParameterMenuItem(getString("gb.time.today"), "db", db.toString(), clonedParams));
			} else {
				String txt = MessageFormat.format(lastDaysPattern, db);
				items.add(new ParameterMenuItem(txt, "db", db.toString(), clonedParams));
			}
		}
		items.add(new MenuDivider());
		return items;
	}

	protected List<RepositoryModel> getRepositories(PageParameters params) {
		if (params == null) {
			return getRepositoryModels();
		}

		boolean hasParameter = false;
		String projectName = WicketUtils.getProjectName(params);
		String userName = WicketUtils.getUsername(params);
		if (StringUtils.isEmpty(projectName)) {
			if (!StringUtils.isEmpty(userName)) {
				projectName = ModelUtils.getPersonalPath(userName);
			}
		}
		String repositoryName = WicketUtils.getRepositoryName(params);
		String set = WicketUtils.getSet(params);
		String regex = WicketUtils.getRegEx(params);
		String team = WicketUtils.getTeam(params);
		int daysBack = params.getInt("db", 0);
		int maxDaysBack = app().settings().getInteger(Keys.web.activityDurationMaximum, 30);

		List<RepositoryModel> availableModels = getRepositoryModels();
		Set<RepositoryModel> models = new HashSet<RepositoryModel>();

		if (!StringUtils.isEmpty(repositoryName)) {
			// try named repository
			hasParameter = true;
			for (RepositoryModel model : availableModels) {
				if (model.name.equalsIgnoreCase(repositoryName)) {
					models.add(model);
					break;
				}
			}
		}

		if (!StringUtils.isEmpty(projectName)) {
			// try named project
			hasParameter = true;
			if (projectName.equalsIgnoreCase(app().settings().getString(Keys.web.repositoryRootGroupName, "main"))) {
				// root project/group
				for (RepositoryModel model : availableModels) {
					if (model.name.indexOf('/') == -1) {
						models.add(model);
					}
				}
			} else {
				// named project/group
				String group = projectName.toLowerCase() + "/";
				for (RepositoryModel model : availableModels) {
					if (model.name.toLowerCase().startsWith(group)) {
						models.add(model);
					}
				}
			}
		}

		if (!StringUtils.isEmpty(regex)) {
			// filter the repositories by the regex
			hasParameter = true;
			Pattern pattern = Pattern.compile(regex);
			for (RepositoryModel model : availableModels) {
				if (pattern.matcher(model.name).find()) {
					models.add(model);
				}
			}
		}

		if (!StringUtils.isEmpty(set)) {
			// filter the repositories by the specified sets
			hasParameter = true;
			List<String> sets = StringUtils.getStringsFromValue(set, ",");
			for (RepositoryModel model : availableModels) {
				for (String curr : sets) {
					if (model.federationSets.contains(curr)) {
						models.add(model);
					}
				}
			}
		}

		if (!StringUtils.isEmpty(team)) {
			// filter the repositories by the specified teams
			hasParameter = true;
			List<String> teams = StringUtils.getStringsFromValue(team, ",");

			// need TeamModels first
			List<TeamModel> teamModels = new ArrayList<TeamModel>();
			for (String name : teams) {
				TeamModel teamModel = app().users().getTeamModel(name);
				if (teamModel != null) {
					teamModels.add(teamModel);
				}
			}

			// brute-force our way through finding the matching models
			for (RepositoryModel repositoryModel : availableModels) {
				for (TeamModel teamModel : teamModels) {
					if (teamModel.hasRepositoryPermission(repositoryModel.name)) {
						models.add(repositoryModel);
					}
				}
			}
		}

		if (!hasParameter) {
			models.addAll(availableModels);
		}

		// time-filter the list
		if (daysBack > 0) {
			if (maxDaysBack > 0 && daysBack > maxDaysBack) {
				daysBack = maxDaysBack;
			}
			Calendar cal = Calendar.getInstance();
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);
			cal.add(Calendar.DATE, -1 * daysBack);
			Date threshold = cal.getTime();
			Set<RepositoryModel> timeFiltered = new HashSet<RepositoryModel>();
			for (RepositoryModel model : models) {
				if (model.lastChange.after(threshold)) {
					timeFiltered.add(model);
				}
			}
			models = timeFiltered;
		}

		List<RepositoryModel> list = new ArrayList<RepositoryModel>(models);
		Collections.sort(list);
		return list;
	}

	/**
	 * Inline login form.
	 */
	private class LoginForm extends Fragment {
		private static final long serialVersionUID = 1L;

		public LoginForm(String id, String markupId, MarkupContainer markupProvider) {
			super(id, markupId, markupProvider);
			setRenderBodyOnly(true);

			SessionlessForm<Void> loginForm = new SessionlessForm<Void>("loginForm", RootPage.this.getClass(), getPageParameters()) {

				private static final long serialVersionUID = 1L;

				@Override
				public void onSubmit() {
					String username = RootPage.this.username.getObject();
					char[] password = RootPage.this.password.getObject().toCharArray();

					HttpServletRequest request = ((WebRequest)RequestCycle.get().getRequest()).getHttpServletRequest();

					UserModel user = app().authentication().authenticate(username, password, request.getRemoteAddr());
					if (user == null) {
						error(getString("gb.invalidUsernameOrPassword"));
					} else if (user.username.equals(Constants.FEDERATION_USER)) {
						// disallow the federation user from logging in via the
						// web ui
						error(getString("gb.invalidUsernameOrPassword"));
						user = null;
					} else {
						loginUser(user);
					}
				}
			};
			TextField<String> unameField = new TextField<String>("username", username);
			WicketUtils.setInputPlaceholder(unameField, markupProvider.getString("gb.username"));
			loginForm.add(unameField);
			NonTrimmedPasswordTextField pwField = new NonTrimmedPasswordTextField("password", password);
			WicketUtils.setInputPlaceholder(pwField, markupProvider.getString("gb.password"));
			loginForm.add(pwField);
			add(loginForm);
		}
	}

	/**
	 * Menu for the authenticated user.
	 */
	class UserMenu extends Fragment {

		private static final long serialVersionUID = 1L;

		public UserMenu(String id, String markupId, MarkupContainer markupProvider) {
			super(id, markupId, markupProvider);
			setRenderBodyOnly(true);
		}

		@Override
		protected void onInitialize() {
			super.onInitialize();

			GitBlitWebSession session = GitBlitWebSession.get();
			UserModel user = session.getUser();
			boolean editCredentials = app().authentication().supportsCredentialChanges(user);
			HttpServletRequest request = ((WebRequest) getRequest()).getHttpServletRequest();
			AuthenticationType authenticationType = (AuthenticationType) request.getAttribute(Constants.ATTRIB_AUTHTYPE);
			boolean standardLogin = (null != authenticationType) ? authenticationType.isStandard() : true;

			if (app().settings().getBoolean(Keys.web.allowGravatar, true)) {
				add(new AvatarImage("username", user, "navbarGravatar", 20, false));
			} else {
				add(new Label("username", user.getDisplayName()));
			}

			List<MenuItem> standardItems = new ArrayList<MenuItem>();
			standardItems.add(new MenuDivider());
			if (user.canAdmin() || user.canCreate()) {
				standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage()));
			}
			standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class,
					WicketUtils.newUsernameParameter(user.username)));
			if (editCredentials) {
				standardItems.add(new PageLinkMenuItem("gb.changePassword", ChangePasswordPage.class));
			}
			standardItems.add(new MenuDivider());
			add(newSubmenu("standardMenu", user.getDisplayName(), standardItems));

			if (showAdmin) {
				// admin menu
				List<MenuItem> adminItems = new ArrayList<MenuItem>();
				adminItems.add(new MenuDivider());
				adminItems.add(new PageLinkMenuItem("gb.users", UsersPage.class));
				adminItems.add(new PageLinkMenuItem("gb.teams", TeamsPage.class));

				boolean showRegistrations = app().federation().canFederate()
						&& app().settings().getBoolean(Keys.web.showFederationRegistrations, false);
				if (showRegistrations) {
					adminItems.add(new PageLinkMenuItem("gb.federation", FederationPage.class));
				}
				adminItems.add(new MenuDivider());

				add(newSubmenu("adminMenu", getString("gb.administration"), adminItems));
			} else {
				add(new Label("adminMenu").setVisible(false));
			}

			// plugin extension items
			List<MenuItem> extensionItems = new ArrayList<MenuItem>();
			List<UserMenuExtension> extensions = app().plugins().getExtensions(UserMenuExtension.class);
			for (UserMenuExtension ext : extensions) {
				List<MenuItem> items = ext.getMenuItems(user);
				extensionItems.addAll(items);
			}

			if (extensionItems.isEmpty()) {
				// no extension items
				add(new Label("extensionsMenu").setVisible(false));
			} else {
				// found extension items
				extensionItems.add(0, new MenuDivider());
				add(newSubmenu("extensionsMenu", getString("gb.extensions"), extensionItems));
				extensionItems.add(new MenuDivider());
			}

			add(new BookmarkablePageLink<Void>("logout",
					LogoutPage.class).setVisible(standardLogin));
		}

		/**
		 * Creates a submenu.  This is not actually submenu because we're using
		 * an older Twitter Bootstrap which is pre-submenu.
		 *
		 * @param wicketId
		 * @param submenuTitle
		 * @param menuItems
		 * @return a submenu fragment
		 */
		private Fragment newSubmenu(String wicketId, String submenuTitle, List<MenuItem> menuItems) {
			Fragment submenu = new Fragment(wicketId, "submenuFragment", this);
			submenu.add(new Label("submenuTitle", submenuTitle).setRenderBodyOnly(true));
			ListDataProvider<MenuItem> menuItemsDp = new ListDataProvider<MenuItem>(menuItems);
			DataView<MenuItem> submenuItems = new DataView<MenuItem>("submenuItem", menuItemsDp) {
				private static final long serialVersionUID = 1L;

				@Override
				public void populateItem(final Item<MenuItem> menuItem) {
					final MenuItem item = menuItem.getModelObject();
					String name = item.toString();
					try {
						// try to lookup translation
						name = getString(name);
					} catch (Exception e) {
					}
					if (item instanceof PageLinkMenuItem) {
						// link to another Wicket page
						PageLinkMenuItem pageLink = (PageLinkMenuItem) item;
						menuItem.add(new LinkPanel("submenuLink", null, null, name, pageLink.getPageClass(),
								pageLink.getPageParameters(), false).setRenderBodyOnly(true));
					} else if (item instanceof ExternalLinkMenuItem) {
						// link to a specified href
						ExternalLinkMenuItem extLink = (ExternalLinkMenuItem) item;
						menuItem.add(new LinkPanel("submenuLink", null, name, extLink.getHref(),
								extLink.openInNewWindow()).setRenderBodyOnly(true));
					} else if (item instanceof MenuDivider) {
						// divider
						menuItem.add(new Label("submenuLink").setRenderBodyOnly(true));
						WicketUtils.setCssClass(menuItem, "divider");
					}
				}
			};
			submenu.add(submenuItems);
			submenu.setRenderBodyOnly(true);
			return submenu;
		}
	}
}
