// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.google.gitiles;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError;
import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_REPOSITORY;

import com.google.common.base.Strings;
import java.io.IOException;
import java.util.Map;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.http.server.glue.WrappedRequest;
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Filter to parse URLs and convert them to {@link GitilesView}s. */
public class ViewFilter extends AbstractHttpFilter {
  private static final Logger log = LoggerFactory.getLogger(ViewFilter.class);
  // TODO(dborowitz): Make this public in JGit (or implement getRegexGroup
  // upstream).
  private static final String REGEX_GROUPS_ATTRIBUTE =
      "org.eclipse.jgit.http.server.glue.MetaServlet.serveRegex";

  private static final String VIEW_ATTRIBUTE = ViewFilter.class.getName() + "/View";

  private static final String CMD_ARCHIVE = "+archive";
  private static final String CMD_AUTO = "+";
  private static final String CMD_BLAME = "+blame";
  private static final String CMD_DESCRIBE = "+describe";
  private static final String CMD_DIFF = "+diff";
  private static final String CMD_LOG = "+log";
  private static final String CMD_REFS = "+refs";
  private static final String CMD_SHOW = "+show";
  private static final String CMD_DOC = "+doc";

  public static GitilesView getView(HttpServletRequest req) {
    return (GitilesView) req.getAttribute(VIEW_ATTRIBUTE);
  }

  static String getRegexGroup(HttpServletRequest req, int groupId) {
    WrappedRequest[] groups = (WrappedRequest[]) req.getAttribute(REGEX_GROUPS_ATTRIBUTE);
    return checkNotNull(groups)[groupId].getPathInfo();
  }

  static void setView(HttpServletRequest req, GitilesView view) {
    req.setAttribute(VIEW_ATTRIBUTE, view);
  }

  static void removeView(HttpServletRequest req) {
    req.removeAttribute(VIEW_ATTRIBUTE);
  }

  static String trimLeadingSlash(String str) {
    return checkLeadingSlash(str).substring(1);
  }

  private static String checkLeadingSlash(String str) {
    checkArgument(str.startsWith("/"), "expected string starting with a slash: %s", str);
    return str;
  }

  private static boolean isEmptyOrSlash(String path) {
    return path.isEmpty() || path.equals("/");
  }

  private static boolean hasRepository(HttpServletRequest req) {
    return req.getAttribute(ATTRIBUTE_REPOSITORY) != null;
  }

  private final GitilesUrls urls;
  private final GitilesAccess.Factory accessFactory;
  private final VisibilityCache visibilityCache;

  public ViewFilter(
      GitilesAccess.Factory accessFactory, GitilesUrls urls, VisibilityCache visibilityCache) {
    this.urls = checkNotNull(urls, "urls");
    this.accessFactory = checkNotNull(accessFactory, "accessFactory");
    this.visibilityCache = checkNotNull(visibilityCache, "visibilityCache");
  }

  @Override
  public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    GitilesView.Builder view;
    try {
      view = parse(req);
    } catch (ServiceMayNotContinueException e) {
      sendError(req, res, e.getStatusCode(), e.getMessage());
      return;
    } catch (IOException err) {
      String name = urls.getHostName(req);
      log.warn("Cannot parse view" + (name != null ? " for " + name : ""), err);
      res.setStatus(SC_SERVICE_UNAVAILABLE);
      return;
    }
    if (view == null) {
      res.setStatus(SC_NOT_FOUND);
      return;
    }

    @SuppressWarnings("unchecked")
    Map<String, String[]> params = req.getParameterMap();
    view.setHostName(urls.getHostName(req))
        .setServletPath(req.getContextPath() + req.getServletPath())
        .putAllParams(params);
    if (normalize(view, res)) {
      return;
    }

    setView(req, view.build());
    try {
      chain.doFilter(req, res);
    } finally {
      removeView(req);
    }
  }

  private boolean normalize(GitilesView.Builder view, HttpServletResponse res) throws IOException {
    if (view.getOldRevision() != Revision.NULL) {
      return false;
    }
    Revision r = view.getRevision();
    Revision nr = Revision.normalizeParentExpressions(r);
    if (r != nr) {
      res.sendRedirect(view.setRevision(nr).toUrl());
      return true;
    }
    return false;
  }

  private GitilesView.Builder parse(HttpServletRequest req) throws IOException {
    String repoName = trimLeadingSlash(getRegexGroup(req, 1));
    if (repoName.isEmpty()) {
      return GitilesView.hostIndex();
    }
    String command = getRegexGroup(req, 2);
    String path = getRegexGroup(req, 3);

    if (command.isEmpty()) {
      return parseNoCommand(req, repoName);
    }
    if (!hasRepository(req)) {
      return null; // no repository? return null to 404.
    }
    if (command.equals(CMD_ARCHIVE)) {
      return parseArchiveCommand(req, repoName, path);
    } else if (command.equals(CMD_AUTO)) {
      return parseAutoCommand(req, repoName, path);
    } else if (command.equals(CMD_BLAME)) {
      return parseBlameCommand(req, repoName, path);
    } else if (command.equals(CMD_DESCRIBE)) {
      return parseDescribeCommand(repoName, path);
    } else if (command.equals(CMD_DIFF)) {
      return parseDiffCommand(req, repoName, path);
    } else if (command.equals(CMD_LOG)) {
      return parseLogCommand(req, repoName, path);
    } else if (command.equals(CMD_REFS)) {
      return parseRefsCommand(repoName, path);
    } else if (command.equals(CMD_SHOW)) {
      return parseShowCommand(req, repoName, path);
    } else if (command.equals(CMD_DOC)) {
      return parseDocCommand(req, repoName, path);
    } else {
      return null;
    }
  }

  private GitilesView.Builder parseNoCommand(HttpServletRequest req, String repoName) {
    if (!hasRepository(req)) {
      return GitilesView.hostIndex().setRepositoryPrefix(repoName);
    }
    return GitilesView.repositoryIndex().setRepositoryName(repoName);
  }

  private GitilesView.Builder parseArchiveCommand(
      HttpServletRequest req, String repoName, String path) throws IOException {
    String ext = null;
    for (String e : ArchiveFormat.allExtensions()) {
      if (path.endsWith(e)) {
        path = path.substring(0, path.length() - e.length());
        ext = e;
        break;
      }
    }
    if (ext == null || path.endsWith("/")) {
      return null;
    }
    RevisionParser.Result result = parseRevision(req, path);
    if (result == null || result.getOldRevision() != null) {
      return null;
    }
    return GitilesView.archive()
        .setRepositoryName(repoName)
        .setRevision(result.getRevision())
        .setPathPart(Strings.emptyToNull(result.getPath()))
        .setExtension(ext);
  }

  private GitilesView.Builder parseAutoCommand(HttpServletRequest req, String repoName, String path)
      throws IOException {
    // Note: if you change the mapping for +, make sure to change
    // GitilesView.toUrl() correspondingly.
    if (path.isEmpty()) {
      return null;
    }
    RevisionParser.Result result = parseRevision(req, path);
    if (result == null) {
      return null;
    }
    if (result.getOldRevision() != null) {
      return parseDiffCommand(repoName, result);
    }
    GitilesView.Builder b = parseShowCommand(repoName, result);
    if (b != null && b.getPathPart() != null && b.getPathPart().endsWith(".md")) {
      return GitilesView.doc()
          .setRepositoryName(repoName)
          .setRevision(result.getRevision())
          .setPathPart(result.getPath());
    }
    return b;
  }

  private GitilesView.Builder parseBlameCommand(
      HttpServletRequest req, String repoName, String path) throws IOException {
    if (path.isEmpty()) {
      return null;
    }
    RevisionParser.Result result = parseRevision(req, path);
    if (result == null || result.getOldRevision() != null || result.getPath().isEmpty()) {
      return null;
    }
    return GitilesView.blame()
        .setRepositoryName(repoName)
        .setRevision(result.getRevision())
        .setPathPart(result.getPath());
  }

  private GitilesView.Builder parseDescribeCommand(String repoName, String path) {
    if (isEmptyOrSlash(path)) {
      return null;
    }
    return GitilesView.describe().setRepositoryName(repoName).setPathPart(path);
  }

  private GitilesView.Builder parseDiffCommand(HttpServletRequest req, String repoName, String path)
      throws IOException {
    return parseDiffCommand(repoName, parseRevision(req, path));
  }

  private GitilesView.Builder parseDiffCommand(String repoName, RevisionParser.Result result) {
    if (result == null) {
      return null;
    }
    return GitilesView.diff()
        .setRepositoryName(repoName)
        .setRevision(result.getRevision())
        .setOldRevision(result.getOldRevision())
        .setPathPart(result.getPath());
  }

  private GitilesView.Builder parseLogCommand(HttpServletRequest req, String repoName, String path)
      throws IOException {
    if (isEmptyOrSlash(path)) {
      return GitilesView.log().setRepositoryName(repoName);
    }
    RevisionParser.Result result = parseRevision(req, path);
    if (result == null) {
      return null;
    }
    return GitilesView.log()
        .setRepositoryName(repoName)
        .setRevision(result.getRevision())
        .setOldRevision(result.getOldRevision())
        .setPathPart(result.getPath());
  }

  private GitilesView.Builder parseRefsCommand(String repoName, String path) {
    return GitilesView.refs().setRepositoryName(repoName).setPathPart(path);
  }

  private GitilesView.Builder parseShowCommand(HttpServletRequest req, String repoName, String path)
      throws IOException {
    return parseShowCommand(repoName, parseRevision(req, path));
  }

  private GitilesView.Builder parseShowCommand(String repoName, RevisionParser.Result result) {
    if (result == null || result.getOldRevision() != null) {
      return null;
    }
    if (result.getPath().isEmpty()) {
      return GitilesView.revision().setRepositoryName(repoName).setRevision(result.getRevision());
    }
    return GitilesView.path()
        .setRepositoryName(repoName)
        .setRevision(result.getRevision())
        .setPathPart(result.getPath());
  }

  private GitilesView.Builder parseDocCommand(HttpServletRequest req, String repoName, String path)
      throws IOException {
    return parseDocCommand(repoName, parseRevision(req, path));
  }

  private GitilesView.Builder parseDocCommand(String repoName, RevisionParser.Result result) {
    if (result == null || result.getOldRevision() != null) {
      return null;
    }
    GitilesView.Builder b =
        GitilesView.doc().setRepositoryName(repoName).setRevision(result.getRevision());
    if (!result.getPath().isEmpty()) {
      b.setPathPart(result.getPath());
    }
    return b;
  }

  private RevisionParser.Result parseRevision(HttpServletRequest req, String path)
      throws IOException {
    RevisionParser revParser =
        new RevisionParser(
            ServletUtils.getRepository(req), accessFactory.forRequest(req), visibilityCache);
    return revParser.parse(checkLeadingSlash(path));
  }
}
