// 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.base.Preconditions.checkState;
import static com.google.gitiles.GitilesServlet.STATIC_PREFIX;
import static com.google.gitiles.Renderer.fileUrlMapper;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.gitiles.blame.BlameCache;
import com.google.gitiles.blame.BlameCacheImpl;
import com.google.gitiles.blame.BlameServlet;
import com.google.gitiles.doc.DocServlet;
import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.http.server.glue.MetaFilter;
import org.eclipse.jgit.http.server.glue.ServletBinder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.transport.resolver.FileResolver;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;

/**
 * MetaFilter to serve Gitiles.
 *
 * <p>Do not use directly; use {@link GitilesServlet}.
 */
class GitilesFilter extends MetaFilter {

  // The following regexes have the following capture groups:
  // 1. The whole string, which causes RegexPipeline to set REGEX_GROUPS but
  //    not otherwise modify the original request.
  // 2. The repository name part, before /<CMD>.
  // 3. The command, <CMD>, with no slashes and beginning with +. Commands have
  //    names analogous to (but not exactly the same as) git command names, such
  //    as "+log" and "+show". The bare command "+" maps to one of the other
  //    commands based on the revision/path, and may change over time.
  // 4. The revision/path part, after /<CMD> (called just "path" below). This is
  //    split into a revision and a path by RevisionParser.

  private static final String CMD = "\\+[a-z0-9-]*";

  @VisibleForTesting
  static final Pattern ROOT_REGEX =
      Pattern.compile(
          ""
              + "^(      " // 1. Everything
              + "  /*    " // Excess slashes
              + "  (/)   " // 2. Repo name (just slash)
              + "  ()    " // 3. Command
              + "  ()    " // 4. Path
              + ")$      ",
          Pattern.COMMENTS);

  @VisibleForTesting
  static final Pattern REPO_REGEX =
      Pattern.compile(
          ""
              + "^(                     " // 1. Everything
              + "  /*                   " // Excess slashes
              + "  (                    " // 2. Repo name
              + "   /                   " // Leading slash
              + "   (?:.(?!             " // Anything, as long as it's not followed by...
              + "        /"
              + CMD
              + "/  " // the special "/<CMD>/" separator,
              + "        |/"
              + CMD
              + "$ " // or "/<CMD>" at the end of the string
              + "        ))*?           "
              + "  )                    "
              + "  /*                   " // Trailing slashes
              + "  ()                   " // 3. Command
              + "  ()                   " // 4. Path
              + ")$                     ",
          Pattern.COMMENTS);

  @VisibleForTesting
  static final Pattern REPO_PATH_REGEX =
      Pattern.compile(
          ""
              + "^(              " // 1. Everything
              + "  /*            " // Excess slashes
              + "  (             " // 2. Repo name
              + "   /            " // Leading slash
              + "   .*?          " // Anything, non-greedy
              + "  )             "
              + "  /("
              + CMD
              + ")" // 3. Command
              + "  (             " // 4. Path
              + "   (?:/.*)?     " // Slash path, or nothing.
              + "  )             "
              + ")$              ",
          Pattern.COMMENTS);

  private static class DispatchFilter extends AbstractHttpFilter {
    private final ListMultimap<GitilesView.Type, Filter> filters;
    private final Map<GitilesView.Type, HttpServlet> servlets;

    private DispatchFilter(
        ListMultimap<GitilesView.Type, Filter> filters,
        Map<GitilesView.Type, HttpServlet> servlets) {
      this.filters = LinkedListMultimap.create(filters);
      this.servlets = ImmutableMap.copyOf(servlets);
      for (GitilesView.Type type : GitilesView.Type.values()) {
        checkState(servlets.containsKey(type), "Missing handler for view %s", type);
      }
    }

    @Override
    public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
        throws IOException, ServletException {
      GitilesView view = checkNotNull(ViewFilter.getView(req));
      final Iterator<Filter> itr = filters.get(view.getType()).iterator();
      final HttpServlet servlet = servlets.get(view.getType());
      new FilterChain() {
        @Override
        public void doFilter(ServletRequest req, ServletResponse res)
            throws IOException, ServletException {
          if (itr.hasNext()) {
            itr.next().doFilter(req, res, this);
          } else {
            servlet.service(req, res);
          }
        }
      }.doFilter(req, res);
    }
  }

  private final ListMultimap<GitilesView.Type, Filter> filters = LinkedListMultimap.create();
  private final Map<GitilesView.Type, HttpServlet> servlets = Maps.newHashMap();

  private Config config;
  private Renderer renderer;
  private GitilesUrls urls;
  private Linkifier linkifier;
  private GitilesAccess.Factory accessFactory;
  private RepositoryResolver<HttpServletRequest> resolver;
  private VisibilityCache visibilityCache;
  private TimeCache timeCache;
  private BlameCache blameCache;
  private GitwebRedirectFilter gitwebRedirect;
  private boolean initialized;

  GitilesFilter() {}

  GitilesFilter(
      Config config,
      Renderer renderer,
      GitilesUrls urls,
      GitilesAccess.Factory accessFactory,
      final RepositoryResolver<HttpServletRequest> resolver,
      VisibilityCache visibilityCache,
      TimeCache timeCache,
      BlameCache blameCache,
      GitwebRedirectFilter gitwebRedirect) {
    this.config = checkNotNull(config, "config");
    this.renderer = renderer;
    this.urls = urls;
    this.accessFactory = accessFactory;
    this.visibilityCache = visibilityCache;
    this.timeCache = timeCache;
    this.blameCache = blameCache;
    this.gitwebRedirect = gitwebRedirect;
    if (resolver != null) {
      this.resolver = resolver;
    }
  }

  @Override
  public synchronized void init(FilterConfig config) throws ServletException {
    super.init(config);
    setDefaultFields(config);

    for (GitilesView.Type type : GitilesView.Type.values()) {
      if (!servlets.containsKey(type)) {
        servlets.put(type, getDefaultHandler(type));
      }
    }

    Filter repositoryFilter = new RepositoryFilter(resolver);
    Filter viewFilter = new ViewFilter(accessFactory, urls, visibilityCache);
    Filter dispatchFilter = new DispatchFilter(filters, servlets);

    ServletBinder root = serveRegex(ROOT_REGEX).through(viewFilter);
    if (gitwebRedirect != null) {
      root.through(gitwebRedirect);
    }
    root.through(dispatchFilter);

    serveRegex(REPO_REGEX).through(repositoryFilter).through(viewFilter).through(dispatchFilter);

    serveRegex(REPO_PATH_REGEX)
        .through(repositoryFilter)
        .through(viewFilter)
        .through(dispatchFilter);

    initialized = true;
  }

  public synchronized BaseServlet getDefaultHandler(GitilesView.Type view) {
    checkNotInitialized();
    switch (view) {
      case HOST_INDEX:
        return new HostIndexServlet(accessFactory, renderer, urls);
      case REPOSITORY_INDEX:
        return new RepositoryIndexServlet(accessFactory, renderer, timeCache);
      case REFS:
        return new RefServlet(accessFactory, renderer, timeCache);
      case REVISION:
        return new RevisionServlet(accessFactory, renderer, linkifier());
      case SHOW:
      case PATH:
        return new PathServlet(accessFactory, renderer, urls);
      case DIFF:
        return new DiffServlet(accessFactory, renderer, linkifier());
      case LOG:
        return new LogServlet(accessFactory, renderer, linkifier());
      case DESCRIBE:
        return new DescribeServlet(accessFactory);
      case ARCHIVE:
        return new ArchiveServlet(accessFactory);
      case BLAME:
        return new BlameServlet(accessFactory, renderer, blameCache);
      case DOC:
      case ROOTED_DOC:
        return new DocServlet(accessFactory, renderer);
      default:
        throw new IllegalArgumentException("Invalid view type: " + view);
    }
  }

  public synchronized void setRenderer(Renderer renderer) {
    checkNotInitialized();
    this.renderer = checkNotNull(renderer, "renderer");
  }

  synchronized void addFilter(GitilesView.Type view, Filter filter) {
    checkNotInitialized();
    filters.put(checkNotNull(view, "view"), checkNotNull(filter, "filter for %s", view));
  }

  synchronized void setHandler(GitilesView.Type view, HttpServlet handler) {
    checkNotInitialized();
    servlets.put(checkNotNull(view, "view"), checkNotNull(handler, "handler for %s", view));
  }

  private synchronized void checkNotInitialized() {
    checkState(!initialized, "Gitiles already initialized");
  }

  private synchronized Linkifier linkifier() {
    if (linkifier == null) {
      checkState(urls != null, "GitilesUrls not yet set");
      linkifier = new Linkifier(urls, config);
    }
    return linkifier;
  }

  private void setDefaultFields(FilterConfig filterConfig) throws ServletException {
    setDefaultConfig(filterConfig);
    setDefaultRenderer(filterConfig);
    setDefaultUrls();
    setDefaultAccess();
    setDefaultVisibilityCache();
    setDefaultTimeCache();
    setDefaultBlameCache();
    setDefaultGitwebRedirect();
  }

  private void setDefaultConfig(FilterConfig filterConfig) throws ServletException {
    if (config == null) {
      try {
        config = GitilesConfig.loadDefault(filterConfig);
      } catch (IOException | ConfigInvalidException e) {
        throw new ServletException(e);
      }
    }
  }

  private void setDefaultRenderer(FilterConfig filterConfig) {
    if (renderer == null) {
      renderer =
          new DefaultRenderer(
              filterConfig.getServletContext().getContextPath() + STATIC_PREFIX,
              FluentIterable.from(
                      Arrays.asList(config.getStringList("gitiles", null, "customTemplates")))
                  .transform(fileUrlMapper()),
              firstNonNull(config.getString("gitiles", null, "siteTitle"), "Gitiles"));
    }
  }

  private void setDefaultUrls() throws ServletException {
    if (urls == null) {
      try {
        urls =
            new DefaultUrls(
                config.getString("gitiles", null, "canonicalHostName"),
                getBaseGitUrl(config),
                config.getString("gitiles", null, "gerritUrl"));
      } catch (UnknownHostException e) {
        throw new ServletException(e);
      }
    }
  }

  private void setDefaultAccess() throws ServletException {
    if (accessFactory == null || resolver == null) {
      String basePath = config.getString("gitiles", null, "basePath");
      if (basePath == null) {
        throw new ServletException("gitiles.basePath not set");
      }
      boolean exportAll = config.getBoolean("gitiles", null, "exportAll", false);

      FileResolver<HttpServletRequest> fileResolver;
      if (resolver == null) {
        fileResolver = new FileResolver<>(new File(basePath), exportAll);
        resolver = fileResolver;
      } else if (resolver instanceof FileResolver) {
        fileResolver = (FileResolver<HttpServletRequest>) resolver;
      } else {
        fileResolver = null;
      }
      if (accessFactory == null) {
        checkState(fileResolver != null, "need a FileResolver when GitilesAccess.Factory not set");
        try {
          accessFactory =
              new DefaultAccess.Factory(
                  new File(basePath), getBaseGitUrl(config), config, fileResolver);
        } catch (IOException e) {
          throw new ServletException(e);
        }
      }
    }
  }

  private void setDefaultVisibilityCache() {
    if (visibilityCache == null) {
      if (config.getSubsections("cache").contains("visibility")) {
        visibilityCache =
            new VisibilityCache(false, ConfigUtil.getCacheBuilder(config, "visibility"));
      } else {
        visibilityCache = new VisibilityCache(false);
      }
    }
  }

  private void setDefaultTimeCache() {
    if (timeCache == null) {
      if (config.getSubsections("cache").contains("tagTime")) {
        timeCache = new TimeCache(ConfigUtil.getCacheBuilder(config, "tagTime"));
      } else {
        timeCache = new TimeCache();
      }
    }
  }

  private void setDefaultBlameCache() {
    if (blameCache == null) {
      if (config.getSubsections("cache").contains("blame")) {
        blameCache = new BlameCacheImpl(ConfigUtil.getCacheBuilder(config, "blame"));
      } else {
        blameCache = new BlameCacheImpl();
      }
    }
  }

  private void setDefaultGitwebRedirect() {
    if (gitwebRedirect == null) {
      if (config.getBoolean("gitiles", null, "redirectGitweb", true)) {
        gitwebRedirect = new GitwebRedirectFilter();
      }
    }
  }

  private static String getBaseGitUrl(Config config) throws ServletException {
    String baseGitUrl = config.getString("gitiles", null, "baseGitUrl");
    if (baseGitUrl == null) {
      throw new ServletException("gitiles.baseGitUrl not set");
    }
    return baseGitUrl;
  }
}
