// 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.checkNotNull;
import static com.google.gitiles.GitilesUrls.escapeName;
import static com.google.gitiles.TreeSoyData.resolveTargetUrl;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import static org.eclipse.jgit.lib.Constants.OBJ_TREE;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.BaseEncoding;
import com.google.common.primitives.Bytes;
import com.google.gitiles.GitilesRequestFailureException.FailureReason;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.StopWalkException;
import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.submodule.SubmoduleWalk;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.QuotedString;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Serves an HTML page with detailed information about a path within a tree. */
// TODO(dborowitz): Handle non-UTF-8 names.
public class PathServlet extends BaseServlet {
  private static final long serialVersionUID = 1L;
  private static final Logger log = LoggerFactory.getLogger(PathServlet.class);

  static final String MODE_HEADER = "X-Gitiles-Path-Mode";
  static final String TYPE_HEADER = "X-Gitiles-Object-Type";
  static final String PATH_DETAIL = "com.google.gitiles.templates.PathDetail.pathDetail";

  /**
   * Submodule URLs where we know there is a web page if the user visits the repository URL verbatim
   * in a web browser.
   */
  private static final Pattern VERBATIM_SUBMODULE_URL_PATTERN =
      Pattern.compile(
          "^("
              + Joiner.on('|')
                  .join(
                      "https?://[^.]+.googlesource.com/.*",
                      "https?://[^.]+.googlecode.com/.*",
                      "https?://code.google.com/p/.*",
                      "https?://github.com/.*")
              + ")$",
          Pattern.CASE_INSENSITIVE);

  static final String AUTODIVE_PARAM = "autodive";
  static final String NO_AUTODIVE_VALUE = "0";

  enum FileType {
    TREE(FileMode.TREE),
    SYMLINK(FileMode.SYMLINK),
    REGULAR_FILE(FileMode.REGULAR_FILE),
    EXECUTABLE_FILE(FileMode.EXECUTABLE_FILE),
    GITLINK(FileMode.GITLINK);

    @SuppressWarnings("ImmutableEnumChecker") // FileMode is effectively immutable.
    private final FileMode mode;

    FileType(FileMode mode) {
      this.mode = mode;
    }

    static @Nullable FileType forEntry(TreeWalk tw) {
      int mode = tw.getRawMode(0);
      for (FileType type : values()) {
        if (type.mode.equals(mode)) {
          return type;
        }
      }
      return null;
    }
  }

  private final GitilesUrls urls;

  public PathServlet(GitilesAccess.Factory accessFactory, Renderer renderer, GitilesUrls urls) {
    super(renderer, accessFactory);
    this.urls = checkNotNull(urls, "urls");
  }

  @Override
  protected void doGetHtml(HttpServletRequest req, HttpServletResponse res) throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Repository repo = ServletUtils.getRepository(req);

    try (RevWalk rw = new RevWalk(repo);
        WalkResult wr = WalkResult.forPath(rw, view, false)) {
      if (wr == null) {
        throw new GitilesRequestFailureException(FailureReason.OBJECT_NOT_FOUND);
      }
      switch (wr.type) {
        case TREE:
          showTree(req, res, wr);
          break;
        case SYMLINK:
          showSymlink(req, res, wr);
          break;
        case REGULAR_FILE:
        case EXECUTABLE_FILE:
          showFile(req, res, wr);
          break;
        case GITLINK:
          showGitlink(req, res, wr);
          break;
        default:
          throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_OBJECT_TYPE);
      }
    } catch (LargeObjectException e) {
      throw new GitilesRequestFailureException(FailureReason.OBJECT_TOO_LARGE, e);
    }
  }

  @Override
  protected void doGetText(HttpServletRequest req, HttpServletResponse res) throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Repository repo = ServletUtils.getRepository(req);

    try (RevWalk rw = new RevWalk(repo);
        WalkResult wr = WalkResult.forPath(rw, view, false)) {
      if (wr == null) {
        throw new GitilesRequestFailureException(FailureReason.OBJECT_NOT_FOUND);
      }

      // Write base64 as plain text without modifying any other headers, under
      // the assumption that any hint we can give to a browser that this is
      // base64 data might cause it to try to decode it and render as HTML,
      // which would be bad.
      switch (wr.type) {
        case SYMLINK:
        case REGULAR_FILE:
        case EXECUTABLE_FILE:
          writeBlobText(req, res, wr);
          break;
        case TREE:
          writeTreeText(req, res, wr);
          break;
        case GITLINK:
          writeCommitText(req, res, wr);
          break;
        default:
          throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_OBJECT_TYPE);
      }
    } catch (LargeObjectException e) {
      throw new GitilesRequestFailureException(FailureReason.OBJECT_TOO_LARGE, e);
    }
  }

  public static void setModeHeader(HttpServletResponse res, FileType type) {
    res.setHeader(MODE_HEADER, String.format("%06o", type.mode.getBits()));
  }

  public static void setTypeHeader(HttpServletResponse res, int type) {
    res.setHeader(TYPE_HEADER, Constants.typeString(type));
  }

  private void writeBlobText(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    setTypeHeader(res, wr.type.mode.getObjectType());
    setModeHeader(res, wr.type);
    try (Writer writer = startRenderText(req, res);
        OutputStream out = BaseEncoding.base64().encodingStream(writer)) {
      wr.getObjectReader().open(wr.id).copyTo(out);
    }
  }

  private void writeTreeText(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    setTypeHeader(res, wr.type.mode.getObjectType());
    setModeHeader(res, wr.type);

    try (Writer writer = startRenderText(req, res);
        OutputStream out = BaseEncoding.base64().encodingStream(writer)) {
      // Match git ls-tree format.
      while (wr.tw.next()) {
        FileMode mode = wr.tw.getFileMode(0);
        out.write(Constants.encode(String.format("%06o", mode.getBits())));
        out.write(' ');
        out.write(Constants.encode(Constants.typeString(mode.getObjectType())));
        out.write(' ');
        wr.tw.getObjectId(0).copyTo(out);
        out.write('\t');
        out.write(Constants.encode(QuotedString.GIT_PATH.quote(wr.tw.getNameString())));
        out.write('\n');
      }
    }
  }

  private void writeCommitText(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    setTypeHeader(res, wr.type.mode.getObjectType());
    setModeHeader(res, wr.type);
    try (Writer writer = startRenderText(req, res);
        OutputStream out = BaseEncoding.base64().encodingStream(writer)) {
      wr.tw.getObjectId(0).copyTo(out);
    }
  }

  @Override
  protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Repository repo = ServletUtils.getRepository(req);

    String longStr = req.getParameter("long");
    boolean includeSizes =
        (longStr != null)
            && (longStr.isEmpty() || Boolean.TRUE.equals(StringUtils.toBooleanOrNull(longStr)));

    String recursiveStr = req.getParameter("recursive");
    boolean recursive =
        (recursiveStr != null)
            && (recursiveStr.isEmpty()
                || Boolean.TRUE.equals(StringUtils.toBooleanOrNull(recursiveStr)));

    try (RevWalk rw = new RevWalk(repo);
        WalkResult wr = WalkResult.forPath(rw, view, recursive)) {
      if (wr == null) {
        throw new GitilesRequestFailureException(FailureReason.OBJECT_NOT_FOUND);
      }
      switch (wr.type) {
        case REGULAR_FILE:
          renderJson(
              req,
              res,
              FileJsonData.toJsonData(
                  wr.id, view.getRepositoryName(), view.getRevision().getName(), wr.path),
              FileJsonData.File.class);
          break;
        case TREE:
          renderJson(
              req,
              res,
              TreeJsonData.toJsonData(wr.id, wr.tw, includeSizes, recursive),
              TreeJsonData.Tree.class);
          break;
        case GITLINK:
          renderJson(
              req,
              res,
              GitlinkJsonData.toJsonData(
                  view.getRepositoryName(),
                  getGitlinkRemoteUrl(req, wr),
                  wr.tw.getObjectId(0).name(),
                  wr.path),
              GitlinkJsonData.Gitlink.class);
          break;
        case EXECUTABLE_FILE:
        case SYMLINK:
        default:
          throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_OBJECT_TYPE);
      }
    } catch (LargeObjectException e) {
      throw new GitilesRequestFailureException(FailureReason.OBJECT_TOO_LARGE, e);
    }
  }

  private static @Nullable RevTree getRoot(GitilesView view, RevWalk rw) throws IOException {
    RevObject obj = rw.peel(rw.parseAny(view.getRevision().getId()));
    switch (obj.getType()) {
      case OBJ_COMMIT:
        return ((RevCommit) obj).getTree();
      case OBJ_TREE:
        return (RevTree) obj;
      default:
        return null;
    }
  }

  private static class AutoDiveFilter extends TreeFilter {
    /**
     * @see GitilesView#getBreadcrumbs(List)
     */
    List<Boolean> hasSingleTree;

    private final byte[] pathRaw;
    private int count;
    private boolean done;

    AutoDiveFilter(String pathStr) {
      hasSingleTree = Lists.newArrayList();
      pathRaw = Constants.encode(pathStr);
    }

    @Override
    public boolean include(TreeWalk tw)
        throws MissingObjectException, IncorrectObjectTypeException, IOException {

      count++;
      int cmp = tw.isPathPrefix(pathRaw, pathRaw.length);
      if (cmp > 0) {
        throw StopWalkException.INSTANCE;
      }
      boolean include;
      if (cmp == 0) {
        if (!isDone(tw)) {
          hasSingleTree.add(hasSingleTreeEntry(tw));
        }
        include = true;
      } else {
        include = false;
      }
      if (tw.isSubtree()) {
        count = 0;
      }
      return include;
    }

    private boolean hasSingleTreeEntry(TreeWalk tw) throws IOException {
      if (count != 1 || !FileMode.TREE.equals(tw.getRawMode(0))) {
        return false;
      }
      CanonicalTreeParser p = new CanonicalTreeParser();
      p.reset(tw.getObjectReader(), tw.getObjectId(0));
      p.next();
      return p.eof();
    }

    @Override
    public boolean shouldBeRecursive() {
      return Bytes.indexOf(pathRaw, (byte) '/') >= 0;
    }

    @Override
    public TreeFilter clone() {
      return this;
    }

    private boolean isDone(TreeWalk tw) {
      if (!done) {
        done = pathRaw.length == tw.getPathLength();
      }
      return done;
    }
  }

  /**
   * Encapsulate the result of walking to a single tree.
   *
   * <p>Unlike {@link TreeWalk} itself, supports positioning at the root tree. Includes information
   * to help the auto-dive routine as well.
   */
  private static class WalkResult implements AutoCloseable {
    private static @Nullable WalkResult recursivePath(RevWalk rw, GitilesView view)
        throws IOException {
      RevTree root = getRoot(view, rw);
      String path = view.getPathPart();

      TreeWalk tw;
      if (!path.isEmpty()) {
        try (TreeWalk toRoot = TreeWalk.forPath(rw.getObjectReader(), path, root)) {
          if (toRoot == null) {
            return null;
          }

          ObjectId treeSHA = toRoot.getObjectId(0);

          ObjectLoader treeLoader = rw.getObjectReader().open(treeSHA);
          if (treeLoader.getType() != Constants.OBJ_TREE) {
            return null;
          }

          tw = new TreeWalk(rw.getObjectReader());
          tw.addTree(treeSHA);
        }
      } else {
        tw = new TreeWalk(rw.getObjectReader());
        tw.addTree(root);
      }

      tw.setRecursive(true);
      return new WalkResult(tw, path, root, root, FileType.TREE, ImmutableList.<Boolean>of());
    }

    private static @Nullable WalkResult forPath(RevWalk rw, GitilesView view, boolean recursive)
        throws IOException {
      if (recursive) {
        return recursivePath(rw, view);
      }

      RevTree root = getRoot(view, rw);
      String path = view.getPathPart();
      try (TreeWalk tw = new TreeWalk(rw.getObjectReader())) {
        tw.addTree(root);
        tw.setRecursive(false);
        if (path.isEmpty()) {
          return new WalkResult(tw, path, root, root, FileType.TREE, ImmutableList.<Boolean>of());
        }
        AutoDiveFilter f = new AutoDiveFilter(path);
        tw.setFilter(f);
        while (tw.next()) {
          if (f.isDone(tw)) {
            FileType type = FileType.forEntry(tw);
            ObjectId id = tw.getObjectId(0);
            if (type == FileType.TREE) {
              tw.enterSubtree();
              tw.setRecursive(false);
            }
            return new WalkResult(tw, path, root, id, type, f.hasSingleTree);
          } else if (tw.isSubtree()) {
            tw.enterSubtree();
          }
        }
      } catch (IOException | RuntimeException e) {
        // Fallthrough.
      }
      return null;
    }

    private final TreeWalk tw;
    private final String path;
    private final RevTree root;
    private final ObjectId id;
    private final FileType type;
    private final List<Boolean> hasSingleTree;

    private WalkResult(
        TreeWalk tw,
        String path,
        RevTree root,
        ObjectId objectId,
        FileType type,
        List<Boolean> hasSingleTree) {
      this.tw = tw;
      this.path = path;
      this.root = root;
      this.id = objectId;
      this.type = type;
      this.hasSingleTree = hasSingleTree;
    }

    private ObjectReader getObjectReader() {
      return tw.getObjectReader();
    }

    @Override
    public void close() {
      tw.close();
    }
  }

  private void showTree(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Config cfg = getAccess(req).getConfig();
    List<String> autodive = view.getParameters().get(AUTODIVE_PARAM);
    if (autodive.size() != 1 || !NO_AUTODIVE_VALUE.equals(autodive.get(0))) {
      byte[] path = Constants.encode(view.getPathPart());
      ObjectReader reader = wr.getObjectReader();
      CanonicalTreeParser child = getOnlyChildSubtree(reader, wr.id, path);
      if (child != null) {
        while (true) {
          path = new byte[child.getEntryPathLength()];
          System.arraycopy(child.getEntryPathBuffer(), 0, path, 0, child.getEntryPathLength());
          CanonicalTreeParser next = getOnlyChildSubtree(reader, child.getEntryObjectId(), path);
          if (next == null) {
            break;
          }
          child = next;
        }
        res.sendRedirect(
            GitilesView.path()
                .copyFrom(view)
                .setPathPart(
                    RawParseUtils.decode(child.getEntryPathBuffer(), 0, child.getEntryPathLength()))
                .toUrl());
        return;
      }
    }
    // TODO(sop): Allow caching trees by SHA-1 when no S cookie is sent.
    renderHtml(
        req,
        res,
        PATH_DETAIL,
        ImmutableMap.of(
            "title", !view.getPathPart().isEmpty() ? view.getPathPart() : "/",
            "breadcrumbs", view.getBreadcrumbs(wr.hasSingleTree),
            "type", FileType.TREE.toString(),
            "data",
                new TreeSoyData(wr.getObjectReader(), view, cfg, wr.root, req.getRequestURI())
                    .setArchiveFormat(getArchiveFormat(getAccess(req)))
                    .toSoyData(wr.id, wr.tw)));
  }

  private @Nullable CanonicalTreeParser getOnlyChildSubtree(
      ObjectReader reader, ObjectId id, byte[] prefix) throws IOException {
    CanonicalTreeParser p = new CanonicalTreeParser(prefix, reader, id);
    if (p.eof() || p.getEntryFileMode() != FileMode.TREE) {
      return null;
    }
    p.next(1);
    return p.eof() ? p : null;
  }

  private @Nullable URI createEditUrl(HttpServletRequest req, GitilesView view) throws IOException {
    String baseGerritUrl = this.urls.getBaseGerritUrl(req);
    if (baseGerritUrl == null) {
      return null;
    }
    String commitish = view.getRevision().getName();
    if (commitish == null || !commitish.startsWith("refs/heads/")) {
      return null;
    }
    try {
      URI editUrl = new URI(baseGerritUrl);
      String path =
          String.format(
              "admin/repos/edit/repo/%s/branch/%s/file/%s",
              view.getRepositoryName(), commitish, view.getPathPart());
      return editUrl.resolve(escapeName(path));
    } catch (URISyntaxException use) {
      log.warn("Malformed Edit URL", use);
    }
    return null;
  }

  private void showFile(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Map<String, ?> data =
        new BlobSoyData(wr.getObjectReader(), view)
            .toSoyData(wr.path, wr.id, createEditUrl(req, view));
    // TODO(sop): Allow caching files by SHA-1 when no S cookie is sent.
    renderHtml(
        req,
        res,
        PATH_DETAIL,
        ImmutableMap.of(
            "title", ViewFilter.getView(req).getPathPart(),
            "breadcrumbs", view.getBreadcrumbs(wr.hasSingleTree),
            "type", wr.type.toString(),
            "data", data));
  }

  private void showSymlink(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Map<String, Object> data = Maps.newHashMap();

    ObjectLoader loader = wr.getObjectReader().open(wr.id, OBJ_BLOB);
    String target;
    try {
      target = RawParseUtils.decode(loader.getCachedBytes(TreeSoyData.MAX_SYMLINK_SIZE));
    } catch (LargeObjectException.OutOfMemory e) {
      throw e;
    } catch (LargeObjectException e) {
      data.put("sha", ObjectId.toString(wr.id));
      data.put("data", null);
      data.put("size", Long.toString(loader.getSize()));
      renderHtml(
          req,
          res,
          PATH_DETAIL,
          ImmutableMap.of(
              "title", ViewFilter.getView(req).getPathPart(),
              "breadcrumbs", view.getBreadcrumbs(wr.hasSingleTree),
              "type", FileType.REGULAR_FILE.toString(),
              "data", data));
      return;
    }

    String url =
        resolveTargetUrl(
            GitilesView.path().copyFrom(view).setPathPart(dirname(view.getPathPart())).build(),
            target);
    data.put("title", view.getPathPart());
    data.put("target", target);
    if (url != null) {
      data.put("targetUrl", url);
    }

    // TODO(sop): Allow caching files by SHA-1 when no S cookie is sent.
    renderHtml(
        req,
        res,
        PATH_DETAIL,
        ImmutableMap.of(
            "title", ViewFilter.getView(req).getPathPart(),
            "breadcrumbs", view.getBreadcrumbs(wr.hasSingleTree),
            "type", FileType.SYMLINK.toString(),
            "data", data));
  }

  private static String dirname(String path) {
    while (path.charAt(path.length() - 1) == '/') {
      path = path.substring(0, path.length() - 1);
    }
    int lastSlash = path.lastIndexOf('/');
    if (lastSlash > 0) {
      return path.substring(0, lastSlash);
    } else if (lastSlash == 0) {
      return "/";
    } else {
      return ".";
    }
  }

  private void showGitlink(HttpServletRequest req, HttpServletResponse res, WalkResult wr)
      throws IOException {
    String remoteUrl = getGitlinkRemoteUrl(req, wr);
    Map<String, Object> data = Maps.newHashMap();
    data.put("sha", ObjectId.toString(wr.id));
    data.put("remoteUrl", remoteUrl);

    // TODO(dborowitz): Guess when we can put commit SHAs in the URL.
    String httpUrl = resolveHttpUrl(remoteUrl);
    if (httpUrl != null) {
      data.put("httpUrl", httpUrl);
    }

    // TODO(sop): Allow caching links by SHA-1 when no S cookie is sent.
    renderHtml(
        req,
        res,
        PATH_DETAIL,
        ImmutableMap.of(
            "title", ViewFilter.getView(req).getPathPart(),
            "type", FileType.GITLINK.toString(),
            "data", data));
  }

  private String getGitlinkRemoteUrl(HttpServletRequest req, WalkResult wr) throws IOException {
    GitilesView view = ViewFilter.getView(req);
    String modulesUrl;
    String remoteUrl = null;

    try (SubmoduleWalk sw =
        SubmoduleWalk.forPath(ServletUtils.getRepository(req), wr.root, view.getPathPart())) {
      modulesUrl = sw.getModulesUrl();
      if (modulesUrl != null && (modulesUrl.startsWith("./") || modulesUrl.startsWith("../"))) {
        String moduleRepo = PathUtil.simplifyPathUpToRoot(modulesUrl, view.getRepositoryName());
        if (moduleRepo != null) {
          modulesUrl = urls.getBaseGitUrl(req) + moduleRepo;
        }
      } else {
        remoteUrl = sw.getRemoteUrl();
      }
    } catch (ConfigInvalidException e) {
      throw new IOException(e);
    }
    return remoteUrl != null ? remoteUrl : modulesUrl;
  }

  private static @Nullable String resolveHttpUrl(String remoteUrl) {
    if (remoteUrl == null) {
      return null;
    }
    return VERBATIM_SUBMODULE_URL_PATTERN.matcher(remoteUrl).matches() ? remoteUrl : null;
  }
}
