// Copyright (C) 2015 The Android Open Source Project
//
// 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.gerrit.httpd.raw;

import static java.nio.file.Files.exists;
import static java.nio.file.Files.isReadable;

import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.httpd.XsrfCookieFilter;
import com.google.gerrit.httpd.raw.ResourceServlet.Resource;
import com.google.gerrit.launcher.GerritLauncher;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritOptions;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.experiments.ExperimentFeatures;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Path;
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.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.Config;

public class StaticModule extends ServletModule {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String CACHE = "static_content";

  /**
   * Paths at which we should serve the main PolyGerrit application {@code index.html}.
   *
   * <p>Supports {@code "/*"} as a trailing wildcard.
   */
  public static final ImmutableList<String> POLYGERRIT_INDEX_PATHS =
      ImmutableList.of(
          "/",
          "/c/*",
          "/id/*",
          "/p/*",
          "/q/*",
          "/x/*",
          "/admin/*",
          "/dashboard/*",
          "/groups/self",
          "/settings/*",
          "/Documentation/q/*");

  /**
   * Paths that should be treated as static assets when serving PolyGerrit.
   *
   * <p>Supports {@code "/*"} as a trailing wildcard.
   */
  private static final ImmutableList<String> POLYGERRIT_ASSET_PATHS =
      ImmutableList.of(
          "/behaviors/*",
          "/bower_components/*",
          "/elements/*",
          "/fonts/*",
          "/scripts/*",
          "/styles/*");

  private static final String DOC_SERVLET = "DocServlet";
  private static final String FAVICON_SERVLET = "FaviconServlet";
  private static final String POLYGERRIT_INDEX_SERVLET = "PolyGerritUiIndexServlet";
  private static final String ROBOTS_TXT_SERVLET = "RobotsTxtServlet";

  private final GerritOptions options;
  private Paths paths;

  @Inject
  public StaticModule(GerritOptions options) {
    this.options = options;
  }

  @Provides
  @Singleton
  private Paths getPaths() {
    if (paths == null) {
      paths = new Paths(options);
    }
    return paths;
  }

  @Override
  protected void configureServlets() {
    serveRegex("^/Documentation$").with(named(DOC_SERVLET));
    serveRegex("^/Documentation/$").with(named(DOC_SERVLET));
    serveRegex("^/Documentation/(.+)$").with(named(DOC_SERVLET));
    serve("/static/*").with(SiteStaticDirectoryServlet.class);
    install(
        new CacheModule() {
          @Override
          protected void configure() {
            cache(CACHE, Path.class, Resource.class)
                .maximumWeight(1 << 20)
                .weigher(ResourceServlet.Weigher.class);
          }
        });
    if (!options.headless()) {
      install(new CoreStaticModule());
      install(new PolyGerritModule());
    }
  }

  @Provides
  @Singleton
  @Named(DOC_SERVLET)
  HttpServlet getDocServlet(@Named(CACHE) Cache<Path, Resource> cache) {
    Paths p = getPaths();
    if (p.warFs != null) {
      return new WarDocServlet(cache, p.warFs);
    } else if (p.unpackedWar != null && !p.isDev()) {
      return new DirectoryDocServlet(cache, p.unpackedWar);
    } else {
      return new HttpServlet() {
        private static final long serialVersionUID = 1L;

        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
          resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
      };
    }
  }

  private class CoreStaticModule extends ServletModule {
    @Override
    public void configureServlets() {
      serve("/robots.txt").with(named(ROBOTS_TXT_SERVLET));
      serve("/favicon.ico").with(named(FAVICON_SERVLET));
    }

    @Provides
    @Singleton
    @Named(ROBOTS_TXT_SERVLET)
    HttpServlet getRobotsTxtServlet(
        @GerritServerConfig Config cfg,
        SitePaths sitePaths,
        @Named(CACHE) Cache<Path, Resource> cache) {
      Path configPath = sitePaths.resolve(cfg.getString("httpd", null, "robotsFile"));
      if (configPath != null) {
        if (exists(configPath) && isReadable(configPath)) {
          return new SingleFileServlet(cache, configPath, true);
        }
        logger.atWarning().log("Cannot read httpd.robotsFile, using default");
      }
      Paths p = getPaths();
      if (p.warFs != null) {
        return new SingleFileServlet(cache, p.warFs.getPath("/robots.txt"), false);
      }
      return new SingleFileServlet(cache, webappSourcePath("robots.txt"), true);
    }

    @Provides
    @Singleton
    @Named(FAVICON_SERVLET)
    HttpServlet getFaviconServlet(@Named(CACHE) Cache<Path, Resource> cache) {
      Paths p = getPaths();
      if (p.warFs != null) {
        return new SingleFileServlet(cache, p.warFs.getPath("/favicon.ico"), false);
      }
      return new SingleFileServlet(cache, webappSourcePath("favicon.ico"), true);
    }

    private Path webappSourcePath(String name) {
      Paths p = getPaths();
      if (p.unpackedWar != null) {
        return p.unpackedWar.resolve(name);
      }
      return p.sourceRoot.resolve("webapp/" + name);
    }
  }

  private class PolyGerritModule extends ServletModule {
    @Override
    public void configureServlets() {
      for (String p : POLYGERRIT_INDEX_PATHS) {
        filter(p).through(XsrfCookieFilter.class);
      }
      filter("/*").through(PolyGerritFilter.class);
    }

    @Provides
    @Singleton
    @Named(POLYGERRIT_INDEX_SERVLET)
    HttpServlet getPolyGerritUiIndexServlet(
        @CanonicalWebUrl @Nullable String canonicalUrl,
        @GerritServerConfig Config cfg,
        GerritApi gerritApi,
        ExperimentFeatures experimentFeatures) {
      String cdnPath =
          options.useDevCdn() ? options.devCdn() : cfg.getString("gerrit", null, "cdnPath");
      String faviconPath = cfg.getString("gerrit", null, "faviconPath");
      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures);
    }

    @Provides
    @Singleton
    PolyGerritUiServlet getPolyGerritUiServlet(@Named(CACHE) Cache<Path, Resource> cache) {
      return new PolyGerritUiServlet(cache, polyGerritBasePath());
    }

    private Path polyGerritBasePath() {
      Paths p = getPaths();

      return p.warFs != null
          ? p.warFs.getPath("/polygerrit_ui")
          : p.unpackedWar.resolve("polygerrit_ui");
    }
  }

  private static class Paths {
    private final FileSystem warFs;
    private final Path sourceRoot;
    private final Path unpackedWar;
    private final boolean development;

    private Paths(GerritOptions options) {
      try {
        File launcherLoadedFrom = getLauncherLoadedFrom();
        if (launcherLoadedFrom != null && launcherLoadedFrom.getName().endsWith(".jar")) {
          // Special case: unpacked war archive deployed in container.
          // The path is something like:
          // <container>/<gerrit>/WEB-INF/lib/launcher.jar
          // Switch to exploded war case with <container>/webapp>/<gerrit>
          // root directory
          warFs = null;
          unpackedWar =
              java.nio.file.Paths.get(
                  launcherLoadedFrom.getParentFile().getParentFile().getParentFile().toURI());
          sourceRoot = null;
          development = false;
          return;
        }
        warFs = getDistributionArchive(launcherLoadedFrom);
        if (warFs == null) {
          unpackedWar = makeWarTempDir();
          development = true;
        } else if (options.useDevCdn()) {
          unpackedWar = null;
          development = true;
        } else {
          unpackedWar = null;
          development = false;
          sourceRoot = null;
          return;
        }
      } catch (IOException e) {
        throw new ProvisionException("Error initializing static content paths", e);
      }

      sourceRoot = getSourceRootOrNull();
    }

    private static Path getSourceRootOrNull() {
      try {
        return GerritLauncher.resolveInSourceRoot(".");
      } catch (FileNotFoundException e) {
        return null;
      }
    }

    private FileSystem getDistributionArchive(File war) throws IOException {
      if (war == null) {
        return null;
      }
      return GerritLauncher.getZipFileSystem(war.toPath());
    }

    private File getLauncherLoadedFrom() {
      File war;
      try {
        war = GerritLauncher.getDistributionArchive();
      } catch (IOException e) {
        if ((e instanceof FileNotFoundException)
            && GerritLauncher.NOT_ARCHIVED.equals(e.getMessage())) {
          return null;
        }
        throw new ProvisionException("Error reading gerrit.war", e);
      }
      return war;
    }

    private boolean isDev() {
      return development;
    }

    private Path makeWarTempDir() {
      // Obtain our local temporary directory, but it comes back as a file
      // so we have to switch it to be a directory post creation.
      //
      try {
        File dstwar = GerritLauncher.createTempFile("gerrit_", "war");
        if (!dstwar.delete() || !dstwar.mkdir()) {
          throw new IOException("Cannot mkdir " + dstwar.getAbsolutePath());
        }

        // Jetty normally refuses to serve out of a symlinked directory, as
        // a security feature. Try to resolve out any symlinks in the path.
        //
        try {
          return dstwar.getCanonicalFile().toPath();
        } catch (IOException e) {
          return dstwar.getAbsoluteFile().toPath();
        }
      } catch (IOException e) {
        throw new ProvisionException("Cannot create war tempdir", e);
      }
    }
  }

  private static Key<HttpServlet> named(String name) {
    return Key.get(HttpServlet.class, Names.named(name));
  }

  @Singleton
  private static class PolyGerritFilter implements Filter {
    private final HttpServlet polyGerritIndex;
    private final PolyGerritUiServlet polygerritUI;

    @Inject
    PolyGerritFilter(
        @Named(POLYGERRIT_INDEX_SERVLET) HttpServlet polyGerritIndex,
        PolyGerritUiServlet polygerritUI) {
      this.polyGerritIndex = polyGerritIndex;
      this.polygerritUI = polygerritUI;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
      HttpServletRequest req = (HttpServletRequest) request;
      HttpServletResponse res = (HttpServletResponse) response;

      GuiceFilterRequestWrapper reqWrapper = new GuiceFilterRequestWrapper(req);
      String path = pathInfo(req);

      if (isPolyGerritIndex(path)) {
        polyGerritIndex.service(reqWrapper, res);
        return;
      }
      if (isPolyGerritAsset(path)) {
        polygerritUI.service(reqWrapper, res);
        return;
      }

      chain.doFilter(req, res);
    }

    private static String pathInfo(HttpServletRequest req) {
      String uri = req.getRequestURI();
      String ctx = req.getContextPath();
      return uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
    }

    private static boolean isPolyGerritAsset(String path) {
      return matchPath(POLYGERRIT_ASSET_PATHS, path);
    }

    private static boolean isPolyGerritIndex(String path) {
      return matchPath(POLYGERRIT_INDEX_PATHS, path);
    }

    private static boolean matchPath(Iterable<String> paths, String path) {
      for (String p : paths) {
        if (p.endsWith("/*")) {
          if (path.regionMatches(0, p, 0, p.length() - 1)) {
            return true;
          }
        } else if (p.equals(path)) {
          return true;
        }
      }
      return false;
    }
  }

  private static class GuiceFilterRequestWrapper extends HttpServletRequestWrapper {
    GuiceFilterRequestWrapper(HttpServletRequest req) {
      super(req);
    }

    @Override
    public String getPathInfo() {
      String uri = getRequestURI();
      String ctx = getContextPath();
      // This is a workaround for long standing guice filter bug:
      // https://github.com/google/guice/issues/807
      String res = uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;

      // Match the logic in the ResourceServlet, that re-add "/"
      // for null path info
      if ("/".equals(res)) {
        return null;
      }
      return res;
    }
  }
}
