/*
 * 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.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TimeZone;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.wicket.Application;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RedirectToUrlException;
import org.apache.wicket.markup.html.CSSPackageResource;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.resources.JavascriptResourceReference;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.protocol.http.RequestUtils;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.target.basic.RedirectRequestTarget;
import org.apache.wicket.util.time.Duration;
import org.apache.wicket.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.Keys;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.CacheControl;
import com.gitblit.wicket.GitBlitWebApp;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;

public abstract class BasePage extends SessionPage {

	private transient Logger logger;

	private transient TimeUtils timeUtils;

	public BasePage() {
		super();
		customizeHeader();
	}

	public BasePage(PageParameters params) {
		super(params);
		customizeHeader();
	}

	protected Logger logger() {
		if (logger == null) {
			logger = LoggerFactory.getLogger(getClass());
		}
		return logger;
	}

	private void customizeHeader() {
		if (app().settings().getBoolean(Keys.web.useResponsiveLayout, true)) {
			add(CSSPackageResource.getHeaderContribution("bootstrap/css/bootstrap-responsive.css"));
		}
		if (app().settings().getBoolean(Keys.web.hideHeader, false)) {
			add(CSSPackageResource.getHeaderContribution("hideheader.css"));
		}
	}

	protected String getContextUrl() {
		return getRequest().getRelativePathPrefixToContextRoot();
	}

	protected String getCanonicalUrl() {
		return getCanonicalUrl(getClass(), getPageParameters());
	}

	protected String getCanonicalUrl(Class<? extends BasePage> clazz, PageParameters params) {
		String relativeUrl = urlFor(clazz, params).toString();
		String canonicalUrl = RequestUtils.toAbsolutePath(relativeUrl);
		return canonicalUrl;
	}

	protected void redirectTo(Class<? extends BasePage> pageClass) {
		redirectTo(pageClass, null);
	}

	protected void redirectTo(Class<? extends BasePage> pageClass, PageParameters parameters) {
		String absoluteUrl = getCanonicalUrl(pageClass, parameters);
		getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
	}

	protected String getLanguageCode() {
		return GitBlitWebSession.get().getLocale().getLanguage();
	}

	protected String getCountryCode() {
		return GitBlitWebSession.get().getLocale().getCountry().toLowerCase();
	}

	protected TimeUtils getTimeUtils() {
		if (timeUtils == null) {
			ResourceBundle bundle;
			try {
				bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp", GitBlitWebSession.get().getLocale());
			} catch (Throwable t) {
				bundle = ResourceBundle.getBundle("com.gitblit.wicket.GitBlitWebApp");
			}
			timeUtils = new TimeUtils(bundle, getTimeZone());
		}
		return timeUtils;
	}

	@Override
	protected void onBeforeRender() {
		if (app().isDebugMode()) {
			// strip Wicket tags in debug mode for jQuery DOM traversal
			Application.get().getMarkupSettings().setStripWicketTags(true);
		}
		super.onBeforeRender();
	}

	@Override
	protected void onAfterRender() {
		if (app().isDebugMode()) {
			// restore Wicket debug tags
			Application.get().getMarkupSettings().setStripWicketTags(false);
		}
		super.onAfterRender();
	}

	@Override
	protected void setHeaders(WebResponse response)	{
		// set canonical link as http header for SEO (issue-304)
		// https://support.google.com/webmasters/answer/139394?hl=en
		response.setHeader("Link", MessageFormat.format("<{0}>; rel=\"canonical\"", getCanonicalUrl()));
		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
		if (expires > 0) {
			// pages are personalized for the authenticated user so they must be
			// marked private to prohibit proxy servers from caching them
			response.setHeader("Cache-Control", "private, must-revalidate");
			setLastModified();
		} else {
			// use default Wicket caching behavior
			super.setHeaders(response);
		}

		// XRF vulnerability. issue-500 / ticket-166
		response.setHeader("X-Frame-Options", "SAMEORIGIN");
	}

	/**
	 * Sets the last-modified header date, if appropriate, for this page.  The
	 * date used is determined by the CacheControl annotation.
	 *
	 */
	protected void setLastModified() {
		if (getClass().isAnnotationPresent(CacheControl.class)) {
			CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
			switch (cacheControl.value()) {
			case ACTIVITY:
				setLastModified(app().getLastActivityDate());
				break;
			case BOOT:
				setLastModified(app().getBootDate());
				break;
			case NONE:
				break;
			default:
				logger().warn(getClass().getSimpleName() + ": unhandled LastModified type " + cacheControl.value());
				break;
			}
		}
	}

	/**
	 * Sets the last-modified header field and the expires field.
	 *
	 * @param when
	 */
	protected final void setLastModified(Date when) {
		if (when == null) {
			return;
		}

		if (when.before(app().getBootDate())) {
			// last-modified can not be before the Gitblit boot date
			// this helps ensure that pages are properly refreshed after a
			// server config change
			when = app().getBootDate();
		}

		int expires = app().settings().getInteger(Keys.web.pageCacheExpires, 0);
		WebResponse response = (WebResponse) getResponse();
		response.setLastModifiedTime(Time.valueOf(when));
		response.setDateHeader("Expires", System.currentTimeMillis() + Duration.minutes(expires).getMilliseconds());
	}

	protected String getPageTitle(String repositoryName) {
		String siteName = app().settings().getString(Keys.web.siteName, Constants.NAME);
		if (StringUtils.isEmpty(siteName)) {
			siteName = Constants.NAME;
		}
		if (repositoryName != null && repositoryName.trim().length() > 0) {
			return repositoryName + " - " + siteName;
		} else {
			return siteName;
		}
	}

	protected void setupPage(String repositoryName, String pageName) {
		add(new Label("title", getPageTitle(repositoryName)));
		getBottomScriptContainer();
		String rootLinkUrl = app().settings().getString(Keys.web.rootLink, urlFor(GitBlitWebApp.get().getHomePage(), null).toString());
		ExternalLink rootLink = new ExternalLink("rootLink", rootLinkUrl);
		WicketUtils.setHtmlTooltip(rootLink, app().settings().getString(Keys.web.siteName, Constants.NAME));
		add(rootLink);

		// Feedback panel for info, warning, and non-fatal error messages
		add(new FeedbackPanel("feedback").setOutputMarkupId(true));

		add(new Label("gbVersion", "v" + Constants.getVersion()));
		if (app().settings().getBoolean(Keys.web.aggressiveHeapManagement, false)) {
			System.gc();
		}
	}

	protected Map<AccessRestrictionType, String> getAccessRestrictions() {
		Map<AccessRestrictionType, String> map = new LinkedHashMap<AccessRestrictionType, String>();
		for (AccessRestrictionType type : AccessRestrictionType.values()) {
			switch (type) {
			case NONE:
				map.put(type, getString("gb.notRestricted"));
				break;
			case PUSH:
				map.put(type, getString("gb.pushRestricted"));
				break;
			case CLONE:
				map.put(type, getString("gb.cloneRestricted"));
				break;
			case VIEW:
				map.put(type, getString("gb.viewRestricted"));
				break;
			}
		}
		return map;
	}

	protected Map<AccessPermission, String> getAccessPermissions() {
		Map<AccessPermission, String> map = new LinkedHashMap<AccessPermission, String>();
		for (AccessPermission type : AccessPermission.values()) {
			switch (type) {
			case NONE:
				map.put(type, MessageFormat.format(getString("gb.noPermission"), type.code));
				break;
			case EXCLUDE:
				map.put(type, MessageFormat.format(getString("gb.excludePermission"), type.code));
				break;
			case VIEW:
				map.put(type, MessageFormat.format(getString("gb.viewPermission"), type.code));
				break;
			case CLONE:
				map.put(type, MessageFormat.format(getString("gb.clonePermission"), type.code));
				break;
			case PUSH:
				map.put(type, MessageFormat.format(getString("gb.pushPermission"), type.code));
				break;
			case CREATE:
				map.put(type, MessageFormat.format(getString("gb.createPermission"), type.code));
				break;
			case DELETE:
				map.put(type, MessageFormat.format(getString("gb.deletePermission"), type.code));
				break;
			case REWIND:
				map.put(type, MessageFormat.format(getString("gb.rewindPermission"), type.code));
				break;
			}
		}
		return map;
	}

	protected Map<FederationStrategy, String> getFederationTypes() {
		Map<FederationStrategy, String> map = new LinkedHashMap<FederationStrategy, String>();
		for (FederationStrategy type : FederationStrategy.values()) {
			switch (type) {
			case EXCLUDE:
				map.put(type, getString("gb.excludeFromFederation"));
				break;
			case FEDERATE_THIS:
				map.put(type, getString("gb.federateThis"));
				break;
			case FEDERATE_ORIGIN:
				map.put(type, getString("gb.federateOrigin"));
				break;
			}
		}
		return map;
	}

	protected Map<AuthorizationControl, String> getAuthorizationControls() {
		Map<AuthorizationControl, String> map = new LinkedHashMap<AuthorizationControl, String>();
		for (AuthorizationControl type : AuthorizationControl.values()) {
			switch (type) {
			case AUTHENTICATED:
				map.put(type, getString("gb.allowAuthenticatedDescription"));
				break;
			case NAMED:
				map.put(type, getString("gb.allowNamedDescription"));
				break;
			}
		}
		return map;
	}

	protected TimeZone getTimeZone() {
		return app().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
				.getTimezone() : app().getTimezone();
	}

	protected String getServerName() {
		ServletWebRequest servletWebRequest = (ServletWebRequest) getRequest();
		HttpServletRequest req = servletWebRequest.getHttpServletRequest();
		return req.getServerName();
	}

	protected List<ProjectModel> getProjectModels() {
		final UserModel user = GitBlitWebSession.get().getUser();
		List<ProjectModel> projects = app().projects().getProjectModels(user, true);
		return projects;
	}

	protected List<ProjectModel> getProjects(PageParameters params) {
		if (params == null) {
			return getProjectModels();
		}

		boolean hasParameter = false;
		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<ProjectModel> availableModels = getProjectModels();
		Set<ProjectModel> models = new HashSet<ProjectModel>();

		if (!StringUtils.isEmpty(regex)) {
			// filter the projects by the regex
			hasParameter = true;
			Pattern pattern = Pattern.compile(regex);
			for (ProjectModel model : availableModels) {
				if (pattern.matcher(model.name).find()) {
					models.add(model);
				}
			}
		}

		if (!StringUtils.isEmpty(team)) {
			// filter the projects 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 (ProjectModel projectModel : availableModels) {
				for (String repositoryName : projectModel.repositories) {
					for (TeamModel teamModel : teamModels) {
						if (teamModel.hasRepositoryPermission(repositoryName)) {
							models.add(projectModel);
						}
					}
				}
			}
		}

		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<ProjectModel> timeFiltered = new HashSet<ProjectModel>();
			for (ProjectModel model : models) {
				if (model.lastChange.after(threshold)) {
					timeFiltered.add(model);
				}
			}
			models = timeFiltered;
		}

		List<ProjectModel> list = new ArrayList<ProjectModel>(models);
		Collections.sort(list);
		return list;
	}

	public void warn(String message, Throwable t) {
		logger().warn(message, t);
	}

	public void error(String message, boolean redirect) {
		error(message, null, redirect ? getApplication().getHomePage() : null);
	}

	public void error(String message, Throwable t, boolean redirect) {
		error(message, t, getApplication().getHomePage());
	}

	public void error(String message, Throwable t, Class<? extends Page> toPage) {
		error(message, t, toPage, null);
	}

	public void error(String message, Throwable t, Class<? extends Page> toPage, PageParameters params) {
		if (t == null) {
			logger().error(message  + " for " + GitBlitWebSession.get().getUsername());
		} else {
			logger().error(message  + " for " + GitBlitWebSession.get().getUsername(), t);
		}
		if (toPage != null) {
			GitBlitWebSession.get().cacheErrorMessage(message);
			String relativeUrl = urlFor(toPage, params).toString();
			String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
			throw new RedirectToUrlException(absoluteUrl);
		} else {
			super.error(message);
		}
	}

	public void authenticationError(String message) {
		logger().error(getRequest().getURL() + " for " + GitBlitWebSession.get().getUsername());
		if (!GitBlitWebSession.get().isLoggedIn()) {
			// cache the request if we have not authenticated.
			// the request will continue after authentication.
			GitBlitWebSession.get().cacheRequest(getClass());
		}
		error(message, true);
	}

	protected String readResource(String resource) {
		StringBuilder sb = new StringBuilder();
		InputStream is = null;
		try {
			is = getClass().getResourceAsStream(resource);
			List<String> lines = IOUtils.readLines(is);
			for (String line : lines) {
				sb.append(line).append('\n');
			}
		} catch (IOException e) {

		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
				}
			}
		}
		return sb.toString();
	}

	private RepeatingView getBottomScriptContainer() {
		RepeatingView bottomScriptContainer = (RepeatingView) get("bottomScripts");
		if (bottomScriptContainer == null) {
			bottomScriptContainer = new RepeatingView("bottomScripts");
			bottomScriptContainer.setRenderBodyOnly(true);
			add(bottomScriptContainer);
		}
		return bottomScriptContainer;
	}

	/**
	 * Adds a HTML script element loading the javascript designated by the given path.
	 *
	 * @param scriptPath
	 *            page-relative path to the Javascript resource; normally starts with "scripts/"
	 */
	protected void addBottomScript(String scriptPath) {
		RepeatingView bottomScripts = getBottomScriptContainer();
		Label script = new Label(bottomScripts.newChildId(), "<script type='text/javascript' src='"
				+ urlFor(new JavascriptResourceReference(this.getClass(), scriptPath)) + "'></script>\n");
		bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
	}

	/**
	 * Adds a HTML script element containing the given code.
	 *
	 * @param code
	 *            inline script code
	 */
	protected void addBottomScriptInline(String code) {
		RepeatingView bottomScripts = getBottomScriptContainer();
		Label script = new Label(bottomScripts.newChildId(),
				"<script type='text/javascript'>/*<![CDATA[*/\n" + code + "\n//]]>\n</script>\n");
		bottomScripts.add(script.setEscapeModelStrings(false).setRenderBodyOnly(true));
	}

}
