// Copyright (C) 2012 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.plugins;

import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CHARACTER_ENCODING;
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CONTENT_TYPE;

import com.google.common.base.CharMatcher;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.net.HttpHeaders;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.httpd.resources.Resource;
import com.google.gerrit.httpd.resources.ResourceKey;
import com.google.gerrit.httpd.resources.SmallResource;
import com.google.gerrit.httpd.restapi.RestApiServlet;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.documentation.MarkdownFormatter;
import com.google.gerrit.server.mime.MimeUtilFileTypeRegistry;
import com.google.gerrit.server.plugins.Plugin;
import com.google.gerrit.server.plugins.Plugin.ApiType;
import com.google.gerrit.server.plugins.PluginContentScanner;
import com.google.gerrit.server.plugins.PluginEntry;
import com.google.gerrit.server.plugins.PluginsCollection;
import com.google.gerrit.server.plugins.ReloadPluginListener;
import com.google.gerrit.server.plugins.StartPluginListener;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.util.http.RequestUtil;
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.servlet.GuiceFilter;

import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.jar.Attributes;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.FilterChain;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
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;

@Singleton
class HttpPluginServlet extends HttpServlet
    implements StartPluginListener, ReloadPluginListener {
  private static final int SMALL_RESOURCE = 128 * 1024;
  private static final long serialVersionUID = 1L;
  private static final Logger log
      = LoggerFactory.getLogger(HttpPluginServlet.class);

  private final MimeUtilFileTypeRegistry mimeUtil;
  private final Provider<String> webUrl;
  private final Cache<ResourceKey, Resource> resourceCache;
  private final String sshHost;
  private final int sshPort;
  private final RestApiServlet managerApi;

  private List<Plugin> pending = Lists.newArrayList();
  private ContextMapper wrapper;
  private final ConcurrentMap<String, PluginHolder> plugins
      = Maps.newConcurrentMap();

  @Inject
  HttpPluginServlet(
      MimeUtilFileTypeRegistry mimeUtil,
      @CanonicalWebUrl Provider<String> webUrl,
      @Named(HttpPluginModule.PLUGIN_RESOURCES) Cache<ResourceKey, Resource> cache,
      SshInfo sshInfo,
      RestApiServlet.Globals globals,
      PluginsCollection plugins) {
    this.mimeUtil = mimeUtil;
    this.webUrl = webUrl;
    this.resourceCache = cache;
    this.managerApi = new RestApiServlet(globals, plugins);

    String sshHost = "review.example.com";
    int sshPort = 29418;
    if (!sshInfo.getHostKeys().isEmpty()) {
      String host = sshInfo.getHostKeys().get(0).getHost();
      int c = host.lastIndexOf(':');
      if (0 <= c) {
        sshHost = host.substring(0, c);
        sshPort = Integer.parseInt(host.substring(c+1));
      } else {
        sshHost = host;
        sshPort = 22;
      }
    }
    this.sshHost = sshHost;
    this.sshPort = sshPort;
  }

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

    wrapper = new ContextMapper(config.getServletContext().getContextPath());
    for (Plugin plugin : pending) {
      install(plugin);
    }
    pending = null;
  }

  @Override
  public synchronized void onStartPlugin(Plugin plugin) {
    if (pending != null) {
      pending.add(plugin);
    } else {
      install(plugin);
    }
  }

  @Override
  public void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) {
    install(newPlugin);
  }

  private void install(Plugin plugin) {
    GuiceFilter filter = load(plugin);
    final String name = plugin.getName();
    final PluginHolder holder = new PluginHolder(plugin, filter);
    plugin.add(new RegistrationHandle() {
      @Override
      public void remove() {
        plugins.remove(name, holder);
      }
    });
    plugins.put(name, holder);
  }

  private GuiceFilter load(Plugin plugin) {
    if (plugin.getHttpInjector() != null) {
      final String name = plugin.getName();
      final GuiceFilter filter;
      try {
        filter = plugin.getHttpInjector().getInstance(GuiceFilter.class);
      } catch (RuntimeException e) {
        log.warn(String.format("Plugin %s cannot load GuiceFilter", name), e);
        return null;
      }

      try {
        ServletContext ctx =
            PluginServletContext.create(plugin, wrapper.getFullPath(name));
        filter.init(new WrappedFilterConfig(ctx));
      } catch (ServletException e) {
        log.warn(String.format("Plugin %s failed to initialize HTTP", name), e);
        return null;
      }

      plugin.add(new RegistrationHandle() {
        @Override
        public void remove() {
          filter.destroy();
        }
      });
      return filter;
    }
    return null;
  }

  @Override
  public void service(HttpServletRequest req, HttpServletResponse res)
      throws IOException, ServletException {
    List<String> parts = Lists.newArrayList(
      Splitter.on('/').limit(3).omitEmptyStrings()
        .split(Strings.nullToEmpty(RequestUtil.getEncodedPathInfo(req))));

    if (isApiCall(req, parts)) {
      managerApi.service(req, res);
      return;
    }

    String name = parts.get(0);
    final PluginHolder holder = plugins.get(name);
    if (holder == null) {
      CacheHeaders.setNotCacheable(res);
      res.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    HttpServletRequest wr = wrapper.create(req, name);
    FilterChain chain = new FilterChain() {
      @Override
      public void doFilter(ServletRequest req, ServletResponse res)
          throws IOException {
        onDefault(holder, (HttpServletRequest) req, (HttpServletResponse) res);
      }
    };
    if (holder.filter != null) {
      holder.filter.doFilter(wr, res, chain);
    } else {
      chain.doFilter(wr, res);
    }
  }

  private static boolean isApiCall(HttpServletRequest req, List<String> parts) {
    String method = req.getMethod();
    int cnt = parts.size();
    return cnt == 0
        || (cnt == 1 && ("PUT".equals(method) || "DELETE".equals(method)))
        || (cnt == 2 && parts.get(1).startsWith("gerrit~"));
  }

  private void onDefault(PluginHolder holder,
      HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    if (!"GET".equals(req.getMethod()) && !"HEAD".equals(req.getMethod())) {
      CacheHeaders.setNotCacheable(res);
      res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
      return;
    }

    String pathInfo = RequestUtil.getEncodedPathInfo(req);
    if (pathInfo.length() < 1) {
      Resource.NOT_FOUND.send(req, res);
      return;
    }

    String file = pathInfo.substring(1);
    PluginResourceKey key = PluginResourceKey.create(holder.plugin, file);
    Resource rsc = resourceCache.getIfPresent(key);
    if (rsc != null && req.getHeader(HttpHeaders.IF_MODIFIED_SINCE) == null) {
      rsc.send(req, res);
      return;
    }

    String uri = req.getRequestURI();
    if ("".equals(file)) {
      res.sendRedirect(uri + holder.docPrefix + "index.html");
      return;
    }

    if (file.startsWith(holder.staticPrefix)) {
      if (holder.plugin.getApiType() == ApiType.JS) {
        sendJsPlugin(holder.plugin, key, req, res);
      } else {
        PluginContentScanner scanner = holder.plugin.getContentScanner();
        Optional<PluginEntry> entry = scanner.getEntry(file);
        if (entry.isPresent()) {
          if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
            rsc.send(req, res);
          } else {
            sendResource(scanner, entry.get(), key, res);
          }
        } else {
          resourceCache.put(key, Resource.NOT_FOUND);
          Resource.NOT_FOUND.send(req, res);
        }
      }
    } else if (file.equals(
        holder.docPrefix.substring(0, holder.docPrefix.length() - 1))) {
      res.sendRedirect(uri + "/index.html");
    } else if (file.startsWith(holder.docPrefix) && file.endsWith("/")) {
      res.sendRedirect(uri + "index.html");
    } else if (file.startsWith(holder.docPrefix)) {
      PluginContentScanner scanner = holder.plugin.getContentScanner();
      Optional<PluginEntry> entry = scanner.getEntry(file);
      if (!entry.isPresent()) {
        entry = findSource(scanner, file);
      }
      if (!entry.isPresent() && file.endsWith("/index.html")) {
        String pfx = file.substring(0, file.length() - "index.html".length());
        long pluginLastModified = holder.plugin.getSrcFile().lastModified();
        if (hasUpToDateCachedResource(rsc, pluginLastModified)) {
          rsc.send(req, res);
        } else {
          sendAutoIndex(scanner, pfx, holder.plugin.getName(), key, res,
              pluginLastModified);
        }
      } else if (entry.isPresent() && entry.get().getName().endsWith(".md")) {
        if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
          rsc.send(req, res);
        } else {
          sendMarkdownAsHtml(scanner, entry.get(), holder.plugin.getName(),
              key, res);
        }
      } else if (entry.isPresent()) {
        if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
          rsc.send(req, res);
        } else {
          sendResource(scanner, entry.get(), key, res);
        }
      } else {
        resourceCache.put(key, Resource.NOT_FOUND);
        Resource.NOT_FOUND.send(req, res);
      }
    } else {
      resourceCache.put(key, Resource.NOT_FOUND);
      Resource.NOT_FOUND.send(req, res);
    }
  }

  private boolean hasUpToDateCachedResource(Resource cachedResource, long lastUpdateTime) {
    return cachedResource != null
        && cachedResource.isUnchanged(lastUpdateTime);
  }

  private void appendEntriesSection(PluginContentScanner scanner, List<PluginEntry> entries,
      String sectionTitle, StringBuilder md, String prefix,
      int nameOffset) throws IOException {
    if (!entries.isEmpty()) {
      md.append("## ").append(sectionTitle).append(" ##\n");
      for(PluginEntry entry : entries) {
        String rsrc = entry.getName().substring(prefix.length());
        String entryTitle;
        if (rsrc.endsWith(".html")) {
          entryTitle = rsrc.substring(nameOffset, rsrc.length() - 5).replace('-', ' ');
        } else if (rsrc.endsWith(".md")) {
          entryTitle = extractTitleFromMarkdown(scanner, entry);
          if (Strings.isNullOrEmpty(entryTitle)) {
            entryTitle = rsrc.substring(nameOffset, rsrc.length() - 3).replace('-', ' ');
          }
          rsrc = rsrc.substring(0, rsrc.length() - 3) + ".html";
        } else {
          entryTitle = rsrc.substring(nameOffset).replace('-', ' ');
        }
        md.append(String.format("* [%s](%s)\n", entryTitle, rsrc));
      }
      md.append("\n");
    }
  }

  private void sendAutoIndex(PluginContentScanner scanner,
      String prefix, String pluginName,
      PluginResourceKey cacheKey, HttpServletResponse res,long lastModifiedTime)
      throws IOException {
    List<PluginEntry> cmds = Lists.newArrayList();
    List<PluginEntry> servlets = Lists.newArrayList();
    List<PluginEntry> restApis = Lists.newArrayList();
    List<PluginEntry> docs = Lists.newArrayList();
    PluginEntry about = null;
    Enumeration<PluginEntry> entries = scanner.entries();
    while (entries.hasMoreElements()) {
      PluginEntry entry = entries.nextElement();
      String name = entry.getName();
      Optional<Long> size = entry.getSize();
      if (name.startsWith(prefix)
          && (name.endsWith(".md")
              || name.endsWith(".html"))
              && size.isPresent()
          && 0 < size.get() && size.get() <= SMALL_RESOURCE) {
        name = name.substring(prefix.length());
        if (name.startsWith("cmd-")) {
          cmds.add(entry);
        } else if (name.startsWith("servlet-")) {
          servlets.add(entry);
        } else if (name.startsWith("rest-api-")) {
          restApis.add(entry);
        } else if (name.startsWith("about.")) {
          if (about == null) {
            about = entry;
          }
        } else {
          docs.add(entry);
        }
      }
    }

    Collections.sort(cmds, PluginEntry.COMPARATOR_BY_NAME);
    Collections.sort(docs, PluginEntry.COMPARATOR_BY_NAME);

    StringBuilder md = new StringBuilder();
    md.append(String.format("# Plugin %s #\n", pluginName));
    md.append("\n");
    appendPluginInfoTable(md, scanner.getManifest().getMainAttributes());

    if (about != null) {
      InputStreamReader isr = new InputStreamReader(scanner.getInputStream(about));
      BufferedReader reader = new BufferedReader(isr);
      StringBuilder aboutContent = new StringBuilder();
      String line;
      while ((line = reader.readLine()) != null) {
        line = line.trim();
        if (line.isEmpty()) {
          aboutContent.append("\n");
        } else {
          aboutContent.append(line).append("\n");
        }
      }
      reader.close();

      // Only append the About section if there was anything in it
      if (aboutContent.toString().trim().length() > 0) {
        md.append("## About ##\n");
        md.append("\n").append(aboutContent);
      }
    }

    appendEntriesSection(scanner, docs, "Documentation", md, prefix, 0);
    appendEntriesSection(scanner, servlets, "Servlets", md, prefix, "servlet-".length());
    appendEntriesSection(scanner, restApis, "REST APIs", md, prefix, "rest-api-".length());
    appendEntriesSection(scanner, cmds, "Commands", md, prefix, "cmd-".length());

    sendMarkdownAsHtml(md.toString(), pluginName, cacheKey, res, lastModifiedTime);
  }

  private void sendMarkdownAsHtml(String md, String pluginName,
      PluginResourceKey cacheKey, HttpServletResponse res, long lastModifiedTime)
      throws UnsupportedEncodingException, IOException {
    Map<String, String> macros = Maps.newHashMap();
    macros.put("PLUGIN", pluginName);
    macros.put("SSH_HOST", sshHost);
    macros.put("SSH_PORT", "" + sshPort);
    String url = webUrl.get();
    if (Strings.isNullOrEmpty(url)) {
      url = "http://review.example.com/";
    }
    macros.put("URL", url);

    Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@").matcher(md);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      String key = m.group(2);
      String val = macros.get(key);
      if (m.group(1) != null) {
        m.appendReplacement(sb, "@" + key + "@");
      } else if (val != null) {
        m.appendReplacement(sb, val);
      } else {
        m.appendReplacement(sb, "@" + key + "@");
      }
    }
    m.appendTail(sb);

    byte[] html = new MarkdownFormatter()
      .markdownToDocHtml(sb.toString(), "UTF-8");
    resourceCache.put(cacheKey, new SmallResource(html)
        .setContentType("text/html")
        .setCharacterEncoding("UTF-8")
        .setLastModified(lastModifiedTime));
    res.setContentType("text/html");
    res.setCharacterEncoding("UTF-8");
    res.setContentLength(html.length);
    res.setDateHeader("Last-Modified", lastModifiedTime);
    res.getOutputStream().write(html);
  }

  private static void appendPluginInfoTable(StringBuilder html, Attributes main) {
    if (main != null) {
      String t = main.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
      String n = main.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
      String v = main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
      String u = main.getValue(Attributes.Name.IMPLEMENTATION_URL);
      String a = main.getValue("Gerrit-ApiVersion");

      html.append("<table class=\"plugin_info\">");
      if (!Strings.isNullOrEmpty(t)) {
        html.append("<tr><th>Name</th><td>")
            .append(t)
            .append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(n)) {
        html.append("<tr><th>Vendor</th><td>")
            .append(n)
            .append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(v)) {
        html.append("<tr><th>Version</th><td>")
            .append(v)
            .append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(u)) {
        html.append("<tr><th>URL</th><td>")
            .append(String.format("<a href=\"%s\">%s</a>", u, u))
            .append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(a)) {
        html.append("<tr><th>API Version</th><td>")
            .append(a)
            .append("</td></tr>\n");
      }
      html.append("</table>\n");
    }
  }

  private static String extractTitleFromMarkdown(PluginContentScanner scanner, PluginEntry entry)
        throws IOException {
    String charEnc = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }
    if (charEnc == null) {
      charEnc = "UTF-8";
    }
    return new MarkdownFormatter().extractTitleFromMarkdown(
          readWholeEntry(scanner, entry),
          charEnc);
  }

  private static Optional<PluginEntry> findSource(
      PluginContentScanner scanner, String file) throws IOException {
    if (file.endsWith(".html")) {
      int d = file.lastIndexOf('.');
      return scanner.getEntry(file.substring(0, d) + ".md");
    }
    return Optional.absent();
  }

  private void sendMarkdownAsHtml(PluginContentScanner scanner, PluginEntry entry,
      String pluginName, PluginResourceKey key, HttpServletResponse res)
      throws IOException {
    byte[] rawmd = readWholeEntry(scanner, entry);
    String encoding = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      encoding = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }

    String txtmd = RawParseUtils.decode(
        Charset.forName(encoding != null ? encoding : "UTF-8"),
        rawmd);
    long time = entry.getTime();
    if (0 < time) {
      res.setDateHeader("Last-Modified", time);
    }
    sendMarkdownAsHtml(txtmd, pluginName, key, res, time);
  }

  private void sendResource(PluginContentScanner scanner, PluginEntry entry,
      PluginResourceKey key, HttpServletResponse res)
      throws IOException {
    byte[] data = null;
    Optional<Long> size = entry.getSize();
    if (size.isPresent() && size.get() <= SMALL_RESOURCE) {
      data = readWholeEntry(scanner, entry);
    }

    String contentType = null;
    String charEnc = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      contentType = Strings.emptyToNull(atts.get(ATTR_CONTENT_TYPE));
      charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }
    if (contentType == null) {
      contentType = mimeUtil.getMimeType(entry.getName(), data).toString();
      if ("application/octet-stream".equals(contentType)
          && entry.getName().endsWith(".js")) {
        contentType = "application/javascript";
      } else if ("application/x-pointplus".equals(contentType)
          && entry.getName().endsWith(".css")) {
        contentType = "text/css";
      }
    }

    long time = entry.getTime();
    if (0 < time) {
      res.setDateHeader("Last-Modified", time);
    }
    if (size.isPresent()) {
      res.setHeader("Content-Length", size.get().toString());
    }
    res.setContentType(contentType);
    if (charEnc != null) {
      res.setCharacterEncoding(charEnc);
    }
    if (data != null) {
      resourceCache.put(key, new SmallResource(data)
          .setContentType(contentType)
          .setCharacterEncoding(charEnc)
          .setLastModified(time));
      res.getOutputStream().write(data);
    } else {
      writeToResponse(res, scanner.getInputStream(entry));
    }
  }

  private void sendJsPlugin(Plugin plugin, PluginResourceKey key,
      HttpServletRequest req, HttpServletResponse res) throws IOException {
    File pluginFile = plugin.getSrcFile();
    if (req.getRequestURI().endsWith(getJsPluginPath(plugin))
        && pluginFile.exists()) {
      res.setHeader("Content-Length", Long.toString(pluginFile.length()));
      res.setContentType("application/javascript");
      writeToResponse(res, new FileInputStream(pluginFile));
    } else {
      resourceCache.put(key, Resource.NOT_FOUND);
      Resource.NOT_FOUND.send(req, res);
    }
  }

  private static String getJsPluginPath(Plugin plugin) {
    return String.format("/plugins/%s/static/%s", plugin.getName(), plugin.getSrcFile()
        .getName());
  }

  private void writeToResponse(HttpServletResponse res, InputStream in)
      throws IOException {
    try {
      OutputStream out = res.getOutputStream();
      try {
        byte[] tmp = new byte[1024];
        int n;
        while ((n = in.read(tmp)) > 0) {
          out.write(tmp, 0, n);
        }
      } finally {
        out.close();
      }
    } finally {
      in.close();
    }
  }

  private static byte[] readWholeEntry(PluginContentScanner scanner, PluginEntry entry)
      throws IOException {
    try (InputStream in = scanner.getInputStream(entry)) {
      return IO.readWholeStream(in, entry.getSize().get().intValue()).array();
    }
  }

  private static class PluginHolder {
    final Plugin plugin;
    final GuiceFilter filter;
    final String staticPrefix;
    final String docPrefix;

    PluginHolder(Plugin plugin, GuiceFilter filter) {
      this.plugin = plugin;
      this.filter = filter;
      this.staticPrefix =
        getPrefix(plugin, "Gerrit-HttpStaticPrefix", "static/");
      this.docPrefix =
        getPrefix(plugin, "Gerrit-HttpDocumentationPrefix", "Documentation/");
    }

    private static String getPrefix(Plugin plugin, String attr, String def) {
      File srcFile = plugin.getSrcFile();
      PluginContentScanner scanner = plugin.getContentScanner();
      if (srcFile == null || scanner == PluginContentScanner.EMPTY) {
        return def;
      }
      try {
        String prefix =
            scanner.getManifest().getMainAttributes().getValue(attr);
        if (prefix != null) {
          return CharMatcher.is('/').trimFrom(prefix) + "/";
        } else {
          return def;
        }
      } catch (IOException e) {
        log.warn(String.format("Error getting %s for plugin %s, using default",
            attr, plugin.getName()), e);
        return null;
      }
    }
  }
}
