// 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.Sets;
import com.google.gitiles.GitilesRequestFailureException.FailureReason;
import com.google.gson.reflect.TypeToken;
import com.google.template.soy.data.restricted.NullData;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;

/** Serves the top level index page for a Gitiles host. */
public class HostIndexServlet extends BaseServlet {
  private static final long serialVersionUID = 1L;

  protected final GitilesUrls urls;

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

  private Map<String, RepositoryDescription> list(
      HttpServletRequest req, String prefix, Set<String> branches) throws IOException {
    Map<String, RepositoryDescription> descs;
    try {
      descs = getAccess(req).listRepositories(prefix, branches);
    } catch (ServiceNotEnabledException e) {
      throw new GitilesRequestFailureException(FailureReason.SERVICE_NOT_ENABLED, e);
    } catch (ServiceNotAuthorizedException e) {
      throw new GitilesRequestFailureException(FailureReason.NOT_AUTHORIZED, e);
    }
    if (prefix != null && descs.isEmpty()) {
      throw new GitilesRequestFailureException(FailureReason.REPOSITORY_NOT_FOUND);
    }
    return descs;
  }

  private Map<String, Object> toMapData(
      RepositoryDescription desc, @Nullable String prefix, GitilesView view) {
    return ImmutableMap.<String, Object>builder()
        .put("name", stripPrefix(prefix, desc.name))
        .put("description", Strings.nullToEmpty(desc.description))
        .put(
            "url",
            GitilesView.repositoryIndex().copyFrom(view).setRepositoryName(desc.name).toUrl())
        .build();
  }

  @Override
  protected void doHead(HttpServletRequest req, HttpServletResponse res) throws IOException {
    Optional<FormatType> format = getFormat(req);
    if (!format.isPresent()) {
      throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_RESPONSE_FORMAT);
    }

    GitilesView view = ViewFilter.getView(req);
    String prefix = view.getRepositoryPrefix();
    if (prefix != null) {
      Map<String, RepositoryDescription> descs = list(req, prefix, Collections.emptySet());
      if (descs == null) {
        return;
      }
    }
    switch (format.get()) {
      case HTML:
      case JSON:
      case TEXT:
        res.setStatus(HttpServletResponse.SC_OK);
        res.setContentType(format.get().getMimeType());
        break;
      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);
    String prefix = view.getRepositoryPrefix();
    Map<String, RepositoryDescription> descs = list(req, prefix, parseShowBranch(req));
    if (descs == null) {
      return;
    }

    ImmutableList.Builder<Map<String, Object>> repos = ImmutableList.builder();
    for (RepositoryDescription desc : descs.values()) {
      if (prefix == null || desc.name.startsWith(prefix)) {
        repos.add(toMapData(desc, prefix, view));
      }
    }

    String hostName = urls.getHostName(req);
    List<Map<String, String>> breadcrumbs = null;
    if (prefix != null) {
      hostName = hostName + '/' + prefix;
      breadcrumbs = view.getBreadcrumbs();
    }
    renderHtml(
        req,
        res,
        "com.google.gitiles.templates.HostIndex.hostIndex",
        ImmutableMap.of(
            "hostName",
            hostName,
            "breadcrumbs",
            breadcrumbs != null ? breadcrumbs : NullData.INSTANCE,
            "prefix",
            prefix != null ? prefix + '/' : "",
            "repositories",
            repos.build()));
  }

  @Override
  protected void doGetText(HttpServletRequest req, HttpServletResponse res) throws IOException {
    String prefix = ViewFilter.getView(req).getRepositoryPrefix();
    Set<String> branches = parseShowBranch(req);
    Map<String, RepositoryDescription> descs = list(req, prefix, branches);
    if (descs == null) {
      return;
    }

    try (Writer writer = startRenderText(req, res)) {
      for (RepositoryDescription repo : descs.values()) {
        for (String name : branches) {
          String ref = repo.branches.get(name);
          if (ref == null) {
            // Print stub (forty '-' symbols)
            ref = "----------------------------------------";
          }
          writer.write(ref);
          writer.write(' ');
        }
        writer.write(GitilesUrls.escapeName(stripPrefix(prefix, repo.name)));
        writer.write('\n');
      }
    }
  }

  @Override
  protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
    String prefix = ViewFilter.getView(req).getRepositoryPrefix();
    Map<String, RepositoryDescription> descs = list(req, prefix, parseShowBranch(req));
    if (descs == null) {
      return;
    }
    if (prefix != null) {
      Map<String, RepositoryDescription> r = new LinkedHashMap<>();
      for (Map.Entry<String, RepositoryDescription> e : descs.entrySet()) {
        r.put(stripPrefix(prefix, e.getKey()), e.getValue());
      }
      descs = r;
    }
    renderJson(req, res, descs, new TypeToken<Map<String, RepositoryDescription>>() {}.getType());
  }

  private static String stripPrefix(@Nullable String prefix, String name) {
    if (prefix != null && name.startsWith(prefix)) {
      return name.substring(prefix.length() + 1);
    }
    return name;
  }

  private static Set<String> parseShowBranch(HttpServletRequest req) {
    // Roughly match Gerrit Code Review's /projects/ API by supporting
    // both show-branch and b as query parameters.
    Set<String> branches = Sets.newLinkedHashSet();
    String[] values = req.getParameterValues("show-branch");
    if (values != null) {
      Collections.addAll(branches, values);
    }
    values = req.getParameterValues("b");
    if (values != null) {
      Collections.addAll(branches, values);
    }
    return branches;
  }
}
