// 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 com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.html.types.SafeHtml;
import com.google.gitiles.DateFormatter.Format;
import com.google.gitiles.GitilesRequestFailureException.FailureReason;
import com.google.gitiles.doc.MarkdownConfig;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
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;

/** Serves the index page for a repository, if accessed directly by a browser. */
public class RepositoryIndexServlet extends BaseServlet {
  private static final long serialVersionUID = 1L;

  static final int REF_LIMIT = 10;
  private static final int LOG_LIMIT = 20;
  private static final int LOG_WITH_README_LIMIT = 5;

  private final TimeCache timeCache;

  public RepositoryIndexServlet(
      GitilesAccess.Factory accessFactory, Renderer renderer, TimeCache timeCache) {
    super(renderer, accessFactory);
    this.timeCache = checkNotNull(timeCache, "timeCache");
  }

  @Override
  protected void doHead(HttpServletRequest req, HttpServletResponse res) throws IOException {
    // If the repository didn't exist a prior filter would have 404 replied.
    Optional<FormatType> format = getFormat(req);
    if (!format.isPresent()) {
      throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_RESPONSE_FORMAT);
    }
    switch (format.get()) {
      case HTML:
      case JSON:
        res.setStatus(HttpServletResponse.SC_OK);
        res.setContentType(format.get().getMimeType());
        break;
      case TEXT:
      case DEFAULT:
      default:
        throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_RESPONSE_FORMAT);
    }
  }

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

    try (RevWalk walk = new RevWalk(repo)) {
      Paginator paginator = null;
      Map<String, Object> data = Maps.newHashMapWithExpectedSize(7);
      List<Map<String, Object>> tags = RefServlet.getTagsSoyData(req, timeCache, walk, REF_LIMIT);
      ObjectId headId = repo.resolve(Constants.HEAD);
      if (headId != null) {
        RevObject head = walk.parseAny(headId);
        int limit = LOG_LIMIT;
        Map<String, Object> readme = renderReadme(req, walk, view, access.getConfig(), head);
        if (readme != null) {
          data.putAll(readme);
          limit = LOG_WITH_README_LIMIT;
        }
        // TODO(dborowitz): Handle non-commit or missing HEAD?
        if (head.getType() == Constants.OBJ_COMMIT) {
          walk.reset();
          walk.markStart((RevCommit) head);
          paginator = new Paginator(walk, limit, null);
        }
      }
      if (!data.containsKey("entries")) {
        data.put("entries", ImmutableList.of());
      }
      List<Map<String, Object>> branches = RefServlet.getBranchesSoyData(req, REF_LIMIT);

      data.put("cloneUrl", desc.cloneUrl);
      data.put("mirroredFromUrl", Strings.nullToEmpty(desc.mirroredFromUrl));
      data.put("description", Strings.nullToEmpty(desc.description));
      data.put("branches", trim(branches));
      if (branches.size() > REF_LIMIT) {
        data.put("moreBranchesUrl", GitilesView.refs().copyFrom(view).toUrl());
      }
      data.put("tags", trim(tags));
      data.put("hasLog", paginator != null);
      if (tags.size() > REF_LIMIT) {
        data.put("moreTagsUrl", GitilesView.refs().copyFrom(view).toUrl());
      }
      GitilesConfig.putVariant(getAccess(req).getConfig(), "logEntry", "logEntryVariant", data);

      if (paginator != null) {
        DateFormatter df = new DateFormatter(access, Format.DEFAULT);
        try (OutputStream out =
            startRenderStreamingHtml(
                req, res, "com.google.gitiles.templates.RepositoryIndex.repositoryIndex", data)) {
          Writer w = newWriter(out, res);
          new LogSoyData(req, access, "oneline")
              .renderStreaming(
                  paginator, "HEAD", renderer, w, df, LogSoyData.FooterBehavior.LOG_HEAD);
          w.flush();
        }
      } else {
        renderHtml(req, res, "com.google.gitiles.templates.RepositoryIndex.repositoryIndex", data);
      }
    }
  }

  @Override
  protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
    GitilesAccess access = getAccess(req);
    RepositoryDescription desc = access.getRepositoryDescription();
    renderJson(req, res, desc, new TypeToken<RepositoryDescription>() {}.getType());
  }

  private static <T> List<T> trim(List<T> list) {
    return list.size() > REF_LIMIT ? list.subList(0, REF_LIMIT) : list;
  }

  private static @Nullable Map<String, Object> renderReadme(
      HttpServletRequest req, RevWalk walk, GitilesView view, Config cfg, RevObject head)
      throws IOException {
    RevTree rootTree;
    try {
      rootTree = walk.parseTree(head);
    } catch (IncorrectObjectTypeException notTreeish) {
      return null;
    }

    ReadmeHelper readme =
        new ReadmeHelper(
            walk.getObjectReader(),
            GitilesView.path().copyFrom(view).setRevision(Revision.HEAD).setPathPart("/").build(),
            MarkdownConfig.get(cfg),
            rootTree,
            req.getRequestURI());
    readme.scanTree(rootTree);
    if (readme.isPresent()) {
      SafeHtml html = readme.render();
      if (html != null) {
        return ImmutableMap.<String, Object>of("readmeHtml", html);
      }
    }
    return null;
  }
}
