/*
 * Copyright 2013 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;

import java.util.Date;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.protocol.http.IWebApplicationFactory;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WicketFilter;
import org.apache.wicket.util.string.Strings;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IProjectManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;

/**
 *
 * Customization of the WicketFilter to allow smart browser-side caching of
 * some pages.
 *
 * @author James Moger
 *
 */
@Singleton
public class GitblitWicketFilter extends WicketFilter {

	private IStoredSettings settings;

	private IRuntimeManager runtimeManager;

	private IRepositoryManager repositoryManager;

	private IProjectManager projectManager;

	private GitBlitWebApp webapp;

	@Inject
	public GitblitWicketFilter(
			IStoredSettings settings,
			IRuntimeManager runtimeManager,
			IRepositoryManager repositoryManager,
			IProjectManager projectManager,
			GitBlitWebApp webapp) {

		this.settings = settings;
		this.runtimeManager = runtimeManager;
		this.repositoryManager = repositoryManager;
		this.projectManager = projectManager;
		this.webapp = webapp;
	}

	@Override
	protected IWebApplicationFactory getApplicationFactory() {
		return new IWebApplicationFactory() {
			@Override
			public WebApplication createApplication(WicketFilter filter) {
				return webapp;
			}
		};
	}

	/**
	 * Determines the last-modified date of the requested resource.
	 *
	 * @param servletRequest
	 * @return The last modified time stamp
	 */
	@Override
	protected long getLastModified(final HttpServletRequest servletRequest)	{
		final String pathInfo = getRelativePath(servletRequest);
		if (Strings.isEmpty(pathInfo)) {
			return -1;
		}
		long lastModified = super.getLastModified(servletRequest);
		if (lastModified > -1) {
			return lastModified;
		}

		// try to match request against registered CacheControl pages
		String [] paths = pathInfo.split("/");

		String page = paths[0];
		String repo = "";
		String commitId = "";
		if (paths.length >= 2) {
			repo = paths[1];
		}
		if (paths.length >= 3) {
			commitId = paths[2];
		}

		if (!StringUtils.isEmpty(servletRequest.getParameter("r"))) {
			repo = servletRequest.getParameter("r");
		}
		if (!StringUtils.isEmpty(servletRequest.getParameter("h"))) {
			commitId = servletRequest.getParameter("h");
		}

		repo = repo.replace("%2f", "/").replace("%2F", "/").replace(settings.getChar(Keys.web.forwardSlashCharacter, '/'), '/');

		GitBlitWebApp app = (GitBlitWebApp) getWebApplication();
		int expires = settings.getInteger(Keys.web.pageCacheExpires, 0);
		if (!StringUtils.isEmpty(page) && app.isCacheablePage(page) && expires > 0) {
			// page can be cached by the browser
			CacheControl cacheControl = app.getCacheControl(page);
			Date bootDate = runtimeManager.getBootDate();
			switch (cacheControl.value()) {
			case ACTIVITY:
				// returns the last activity date of the server
				Date activityDate = repositoryManager.getLastActivityDate();
				if (activityDate != null) {
					return activityDate.after(bootDate) ? activityDate.getTime() : bootDate.getTime();
				}
				return bootDate.getTime();
			case BOOT:
				// return the boot date of the server
				return bootDate.getTime();
			case PROJECT:
				// return the latest change date for the project OR the boot date
				ProjectModel project = projectManager.getProjectModel(StringUtils.getRootPath(repo));
				if (project != null) {
					return project.lastChange.after(bootDate) ? project.lastChange.getTime() : bootDate.getTime();
				}
				break;
			case REPOSITORY:
				// return the lastest change date for the repository OR the boot
				// date, whichever is latest
				RepositoryModel repository = repositoryManager.getRepositoryModel(repo);
				if (repository != null && repository.lastChange != null) {
					return repository.lastChange.after(bootDate) ? repository.lastChange.getTime() : bootDate.getTime();
				}
				break;
			case COMMIT:
				// get the date of the specified commit
				if (StringUtils.isEmpty(commitId)) {
					// no commit id, use boot date
					return bootDate.getTime();
				} else {
					// last modified date is the commit date
					Repository r = null;
					try {
						// return the timestamp of the associated commit
						r = repositoryManager.getRepository(repo);
						if (r != null) {
							RevCommit commit = JGitUtils.getCommit(r, commitId);
							if (commit != null) {
								Date date = JGitUtils.getCommitDate(commit);
								return date.after(bootDate) ? date.getTime() : bootDate.getTime();
							}
						}
					} finally {
						if (r != null) {
							r.close();
						}
					}
				}
				break;
			default:
				break;
			}
		}

		return -1;
	}
}
