// 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_GONE;
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.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.
      res.sendError(SC_GONE);
      return;
    }

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

    String url;
    try {
      url =
          view.setHostName(gitwebView.getHostName())
              .setServletPath(gitwebView.getServletPath())
              .toUrl();
    } catch (InvalidViewException e) {
      res.setStatus(SC_GONE);
      return;
    }
    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;
    }
  }
}
