// 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.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.net.HttpHeaders.LOCATION;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_MOVED_PERMANENTLY;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.gitiles.GitilesRequestFailureException.FailureReason;
import com.google.gitiles.GitilesView.InvalidViewException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectId;

/** Filter to redirect Gitweb-style URLs to Gitiles-style URLs. */
public class GitwebRedirectFilter extends AbstractHttpFilter {
  public static class TooManyUriParametersException extends IllegalArgumentException {
    private static final long serialVersionUID = 1L;
  }

  private static final String ARG_SEP = "&|;|%3[Bb]";
  private static final Pattern IS_GITWEB_PATTERN = Pattern.compile("(^|" + ARG_SEP + ")[pa]=");
  private static final Splitter ARG_SPLIT = Splitter.on(Pattern.compile(ARG_SEP));
  private static final Splitter VAR_SPLIT = Splitter.on(Pattern.compile("=|%3[Dd]")).limit(2);
  private static final int MAX_ARGS = 512;

  private final boolean trimDotGit;

  public GitwebRedirectFilter() {
    this(false);
  }

  public GitwebRedirectFilter(boolean trimDotGit) {
    this.trimDotGit = trimDotGit;
  }

  @Override
  public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    GitilesView gitwebView = ViewFilter.getView(req);
    if (!isGitwebStyleQuery(req)) {
      chain.doFilter(req, res);
      return;
    }

    ListMultimap<String, String> params = parse(req.getQueryString());
    String action = getFirst(params, "a");
    String project = getFirst(params, "p");
    String path = Strings.nullToEmpty(getFirst(params, "f"));

    // According to gitweb's perl source code, the primary parameters are these
    // short abbreviated names. When pointing to blob or subtree hash,hashParent
    // are the blob or subtree SHA-1s and hashBase,hashParentBase are commits.
    // When pointing to commits or tags, hash is the commit/tag. Its messy.
    Revision hash = toRevision(getFirst(params, "h"));
    Revision hashBase = toRevision(getFirst(params, "hb"));
    Revision hashParent = toRevision(getFirst(params, "hp"));
    Revision hashParentBase = toRevision(getFirst(params, "hpb"));

    GitilesView.Builder view;
    if ("project_index".equals(action)) {
      view = GitilesView.hostIndex();
      project = null;
    } else if ("summary".equals(action) || "tags".equals(action)) {
      view = GitilesView.repositoryIndex();
    } else if (("commit".equals(action) || "tag".equals(action)) && hash != null) {
      view = GitilesView.revision().setRevision(hash);
    } else if ("log".equals(action) || "shortlog".equals(action)) {
      view = GitilesView.log().setRevision(firstNonNull(hash, Revision.HEAD));
    } else if ("tree".equals(action)) {
      view =
          GitilesView.path().setRevision(firstNonNull(hashBase, Revision.HEAD)).setPathPart(path);
    } else if (("blob".equals(action) || "blob_plain".equals(action))
        && hashBase != null
        && !path.isEmpty()) {
      view = GitilesView.path().setRevision(hashBase).setPathPart(path);
    } else if ("commitdiff".equals(action) && hash != null) {
      view =
          GitilesView.diff()
              .setOldRevision(firstNonNull(hashParent, Revision.NULL))
              .setRevision(hash)
              .setPathPart("");
    } else if ("blobdiff".equals(action)
        && !path.isEmpty()
        && hashParentBase != null
        && hashBase != null) {
      view =
          GitilesView.diff().setOldRevision(hashParentBase).setRevision(hashBase).setPathPart(path);
    } else if ("history".equals(action) && !path.isEmpty()) {
      view = GitilesView.log().setRevision(firstNonNull(hashBase, Revision.HEAD)).setPathPart(path);
    } else {
      // Gitiles does not provide an RSS feed (a=rss,atom,opml)
      // Any other URL is out of date and not valid anymore.
      throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_GITWEB_URL);
    }

    if (!Strings.isNullOrEmpty(project)) {
      view.setRepositoryName(cleanProjectName(project));
    }

    String url;
    try {
      url =
          view.setHostName(gitwebView.getHostName())
              .setServletPath(gitwebView.getServletPath())
              .toUrl();
    } catch (InvalidViewException e) {
      throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_GITWEB_URL, e);
    }
    res.setStatus(SC_MOVED_PERMANENTLY);
    res.setHeader(LOCATION, url);
  }

  private static boolean isGitwebStyleQuery(HttpServletRequest req) {
    String qs = req.getQueryString();
    return qs != null && IS_GITWEB_PATTERN.matcher(qs).find();
  }

  private static String getFirst(ListMultimap<String, String> params, String name) {
    return Iterables.getFirst(params.get(checkNotNull(name)), null);
  }

  private static Revision toRevision(String rev) {
    if (Strings.isNullOrEmpty(rev)) {
      return null;
    } else if ("HEAD".equals(rev) || rev.startsWith("refs/")) {
      return Revision.named(rev);
    } else if (ObjectId.isId(rev)) {
      return Revision.unpeeled(rev, ObjectId.fromString(rev));
    } else {
      return Revision.named(rev);
    }
  }

  private String cleanProjectName(String p) {
    if (p.startsWith("/")) {
      p = p.substring(1);
    }
    if (p.endsWith("/")) {
      p = p.substring(0, p.length() - 1);
    }
    if (trimDotGit && p.endsWith(".git")) {
      p = p.substring(0, p.length() - ".git".length());
    }
    if (p.endsWith("/")) {
      p = p.substring(0, p.length() - 1);
    }
    return p;
  }

  private static ListMultimap<String, String> parse(String query) {
    // Parse a gitweb style query string which uses ";" rather than "&" between
    // key=value pairs. Some user agents encode ";" as "%3B" and/or "=" as
    // "%3D", making a real mess of the query string. Parsing here is
    // approximate because ; shouldn't be the pair separator and %3B might have
    // been a ; within a value.
    // This is why people shouldn't use gitweb.
    ListMultimap<String, String> map = LinkedListMultimap.create();
    for (String piece : ARG_SPLIT.split(query)) {
      if (map.size() > MAX_ARGS) {
        throw new TooManyUriParametersException();
      }

      List<String> pair = VAR_SPLIT.splitToList(piece);
      if (pair.size() == 2) {
        map.put(decode(pair.get(0)), decode(pair.get(1)));
      } else { // no equals sign
        map.put(piece, "");
      }
    }
    return map;
  }

  private static String decode(String str) {
    try {
      return URLDecoder.decode(str, UTF_8.name());
    } catch (UnsupportedEncodingException e) {
      return str;
    }
  }
}
