/*
 * 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;

import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.models.RefModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;

/**
 * Serves the content of a gh-pages branch.
 * 
 * @author James Moger
 * 
 */
public class PagesServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private transient Logger logger = LoggerFactory.getLogger(PagesServlet.class);

	public PagesServlet() {
		super();
	}

	/**
	 * Returns an url to this servlet for the specified parameters.
	 * 
	 * @param baseURL
	 * @param repository
	 * @param path
	 * @return an url
	 */
	public static String asLink(String baseURL, String repository, String path) {
		if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
			baseURL = baseURL.substring(0, baseURL.length() - 1);
		}
		return baseURL + Constants.PAGES + repository + "/" + (path == null ? "" : ("/" + path));
	}

	/**
	 * Retrieves the specified resource from the gh-pages branch of the
	 * repository.
	 * 
	 * @param request
	 * @param response
	 * @throws javax.servlet.ServletException
	 * @throws java.io.IOException
	 */
	private void processRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String path = request.getPathInfo();
		if (path.toLowerCase().endsWith(".git")) {
			// forward to url with trailing /
			// this is important for relative pages links
			response.sendRedirect(request.getServletPath() + path + "/");
			return;
		}
		if (path.charAt(0) == '/') {
			// strip leading /
			path = path.substring(1);
		}

		// determine repository and resource from url
		String repository = "";
		String resource = "";
		Repository r = null;
		int offset = 0;
		while (r == null) {
			int slash = path.indexOf('/', offset);
			if (slash == -1) {
				repository = path;
			} else {
				repository = path.substring(0, slash);
			}
			r = GitBlit.self().getRepository(repository, false);
			offset = slash + 1;
			if (offset > 0) {
				resource = path.substring(offset);
			}
			if (repository.equals(path)) {
				// either only repository in url or no repository found
				break;
			}
		}

		ServletContext context = request.getSession().getServletContext();

		try {
			if (r == null) {
				// repository not found!
				String mkd = MessageFormat.format(
						"# Error\nSorry, no valid **repository** specified in this url: {0}!",
						repository);
				error(response, mkd);
				return;
			}

			// retrieve the content from the repository
			RefModel pages = JGitUtils.getPagesBranch(r);
			RevCommit commit = JGitUtils.getCommit(r, pages.getObjectId().getName());

			if (commit == null) {
				// branch not found!
				String mkd = MessageFormat.format(
						"# Error\nSorry, the repository {0} does not have a **gh-pages** branch!",
						repository);
				error(response, mkd);
				r.close();
				return;
			}

			String [] encodings = GitBlit.getEncodings();

			RevTree tree = commit.getTree();
			byte[] content = null;
			if (StringUtils.isEmpty(resource)) {
				// find resource
				List<String> markdownExtensions = GitBlit.getStrings(Keys.web.markdownExtensions);
				List<String> extensions = new ArrayList<String>(markdownExtensions.size() + 2);
				extensions.add("html");
				extensions.add("htm");
				extensions.addAll(markdownExtensions);
				for (String ext : extensions){
					String file = "index." + ext;
					String stringContent = JGitUtils.getStringContent(r, tree, file, encodings);
					if(stringContent == null){
						continue;
					}
					content = stringContent.getBytes(Constants.ENCODING);
					if (content != null) {
						resource = file;
						// assume text/html unless the servlet container
						// overrides
						response.setContentType("text/html; charset=" + Constants.ENCODING);
						break;
					}
				}
			} else {
				// specific resource
				try {
					String contentType = context.getMimeType(resource);
					if (contentType == null) {
						contentType = "text/plain";
					}
					if (contentType.startsWith("text")) {
						content = JGitUtils.getStringContent(r, tree, resource, encodings).getBytes(
								Constants.ENCODING);
					} else {
						content = JGitUtils.getByteContent(r, tree, resource, false);
					}
					response.setContentType(contentType);
				} catch (Exception e) {
				}
			}

			// no content, try custom 404 page
			if (ArrayUtils.isEmpty(content)) {
				String custom404 = JGitUtils.getStringContent(r, tree, "404.html", encodings);
				if (!StringUtils.isEmpty(custom404)) {
					content = custom404.getBytes(Constants.ENCODING);
				}

				// still no content
				if (ArrayUtils.isEmpty(content)) {
					String str = MessageFormat.format(
							"# Error\nSorry, the requested resource **{0}** was not found.",
							resource);
					content = MarkdownUtils.transformMarkdown(str).getBytes(Constants.ENCODING);
				}

				try {
					// output the content
					logger.warn("Pages 404: " + resource);
					response.setStatus(HttpServletResponse.SC_NOT_FOUND);
					response.getOutputStream().write(content);
					response.flushBuffer();
				} catch (Throwable t) {
					logger.error("Failed to write page to client", t);
				}
				return;
			}

			// check to see if we should transform markdown files
			for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {
				if (resource.endsWith(ext)) {
					String mkd = new String(content, Constants.ENCODING);
					content = MarkdownUtils.transformMarkdown(mkd).getBytes(Constants.ENCODING);
					response.setContentType("text/html; charset=" + Constants.ENCODING);
					break;
				}
			}

			try {
				// output the content
				response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate");
				response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());
				response.getOutputStream().write(content);
				response.flushBuffer();
			} catch (Throwable t) {
				logger.error("Failed to write page to client", t);
			}

			// close the repository
			r.close();
		} catch (Throwable t) {
			logger.error("Failed to write page to client", t);
		}
	}

	private void error(HttpServletResponse response, String mkd) throws ServletException,
			IOException, ParseException {
		String content = MarkdownUtils.transformMarkdown(mkd);
		response.setContentType("text/html; charset=" + Constants.ENCODING);
		response.getWriter().write(content);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		processRequest(request, response);
	}
}
