// 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 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.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.httpd.rpc.plugin.ListPluginsServlet;
import com.google.gerrit.server.MimeUtilFileTypeRegistry;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.documentation.MarkdownFormatter;
import com.google.gerrit.server.plugins.Plugin;
import com.google.gerrit.server.plugins.ReloadPluginListener;
import com.google.gerrit.server.plugins.StartPluginListener;
import com.google.gerrit.server.ssh.SshInfo;
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.lib.Config;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Comparator;
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.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

@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 ListPluginsServlet listServlet;

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

  @Inject
  HttpPluginServlet(MimeUtilFileTypeRegistry mimeUtil,
      @CanonicalWebUrl Provider<String> webUrl,
      @Named(HttpPluginModule.PLUGIN_RESOURCES) Cache<ResourceKey, Resource> cache,
      @GerritServerConfig Config cfg,
      SshInfo sshInfo, ListPluginsServlet listServlet) {
    this.mimeUtil = mimeUtil;
    this.webUrl = webUrl;
    this.resourceCache = cache;
    this.listServlet = listServlet;

    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);

    String path = config.getServletContext().getContextPath();
    base = Strings.nullToEmpty(path) + "/plugins/";
    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 {
        WrappedContext ctx = new WrappedContext(plugin, base + 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 {
    String name = extractName(req);
    if (name.equals("")) {
      listServlet.service(req, res);
      return;
    }
    final PluginHolder holder = plugins.get(name);
    if (holder == null) {
      noCache(res);
      res.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    WrappedRequest wr = new WrappedRequest(req, base + 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 void onDefault(PluginHolder holder,
      HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    if (!"GET".equals(req.getMethod()) && !"HEAD".equals(req.getMethod())) {
      noCache(res);
      res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
      return;
    }

    String uri = req.getRequestURI();
    String ctx = req.getContextPath();
    if (uri.length() <= ctx.length()) {
      Resource.NOT_FOUND.send(req, res);
      return;
    }

    String file = uri.substring(ctx.length() + 1);
    ResourceKey key = new ResourceKey(holder.plugin, file);
    Resource rsc = resourceCache.getIfPresent(key);
    if (rsc != null) {
      rsc.send(req, res);
      return;
    }

    if ("".equals(file)) {
      res.sendRedirect(uri + "Documentation/index.html");
    } else if (file.startsWith("static/")) {
      JarFile jar = holder.plugin.getJarFile();
      JarEntry entry = jar.getJarEntry(file);
      if (exists(entry)) {
        sendResource(jar, entry, key, res);
      } else {
        resourceCache.put(key, Resource.NOT_FOUND);
        Resource.NOT_FOUND.send(req, res);
      }
    } else if (file.equals("Documentation")) {
      res.sendRedirect(uri + "/index.html");
    } else if (file.startsWith("Documentation/") && file.endsWith("/")) {
      res.sendRedirect(uri + "index.html");
    } else if (file.startsWith("Documentation/")) {
      JarFile jar = holder.plugin.getJarFile();
      JarEntry entry = jar.getJarEntry(file);
      if (!exists(entry)) {
        entry = findSource(jar, file);
      }
      if (!exists(entry) && file.endsWith("/index.html")) {
        String pfx = file.substring(0, file.length() - "index.html".length());
        sendAutoIndex(jar, pfx, holder.plugin.getName(), key, res);
      } else if (exists(entry) && entry.getName().endsWith(".md")) {
        sendMarkdownAsHtml(jar, entry, holder.plugin.getName(), key, res);
      } else if (exists(entry)) {
        sendResource(jar, entry, 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 void sendAutoIndex(JarFile jar,
      String prefix, String pluginName,
      ResourceKey cacheKey, HttpServletResponse res) throws IOException {
    List<JarEntry> cmds = Lists.newArrayList();
    List<JarEntry> docs = Lists.newArrayList();
    Enumeration<JarEntry> entries = jar.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = entries.nextElement();
      String name = entry.getName();
      long size = entry.getSize();
      if (name.startsWith(prefix)
          && (name.endsWith(".md")
              || name.endsWith(".html"))
          && 0 < size && size <= SMALL_RESOURCE) {
        if (name.substring(prefix.length()).startsWith("cmd-")) {
          cmds.add(entry);
        } else {
          docs.add(entry);
        }
      }
    }
    Collections.sort(cmds, new Comparator<JarEntry>() {
      @Override
      public int compare(JarEntry a, JarEntry b) {
        return a.getName().compareTo(b.getName());
      }
    });
    Collections.sort(docs, new Comparator<JarEntry>() {
      @Override
      public int compare(JarEntry a, JarEntry b) {
        return a.getName().compareTo(b.getName());
      }
    });

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

    if (!docs.isEmpty()) {
      md.append("## Documentation ##\n");
      for(JarEntry entry : docs) {
        String rsrc = entry.getName().substring(prefix.length());
        String title;
        if (rsrc.endsWith(".html")) {
          title = rsrc.substring(0, rsrc.length() - 5).replace('-', ' ');
        } else if (rsrc.endsWith(".md")) {
          title = extractTitleFromMarkdown(jar, entry);
          if (Strings.isNullOrEmpty(title)) {
            title = rsrc.substring(0, rsrc.length() - 3).replace('-', ' ');
          }
          rsrc = rsrc.substring(0, rsrc.length() - 3) + ".html";
        } else {
          title = rsrc.replace('-', ' ');
        }
        md.append(String.format("* [%s](%s)\n", title, rsrc));
      }
      md.append("\n");
    }

    if (!cmds.isEmpty()) {
      md.append("## Commands ##\n");
      for(JarEntry entry : cmds) {
        String rsrc = entry.getName().substring(prefix.length());
        String title;
        if (rsrc.endsWith(".html")) {
          title = rsrc.substring(4, rsrc.length() - 5).replace('-', ' ');
        } else if (rsrc.endsWith(".md")) {
          title = extractTitleFromMarkdown(jar, entry);
          if (Strings.isNullOrEmpty(title)) {
            title = rsrc.substring(4, rsrc.length() - 3).replace('-', ' ');
          }
          rsrc = rsrc.substring(0, rsrc.length() - 3) + ".html";
        } else {
          title = rsrc.substring(4).replace('-', ' ');
        }
        md.append(String.format("* [%s](%s)\n", title, rsrc));
      }
      md.append("\n");
    }

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

  private void sendMarkdownAsHtml(String md, String pluginName,
      ResourceKey cacheKey, HttpServletResponse res)
      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"));
    res.setContentType("text/html");
    res.setCharacterEncoding("UTF-8");
    res.setContentLength(html.length);
    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(JarFile jar, JarEntry entry)
        throws IOException {
    String charEnc = null;
    Attributes atts = entry.getAttributes();
    if (atts != null) {
      charEnc = Strings.emptyToNull(atts.getValue("Character-Encoding"));
    }
    if (charEnc == null) {
      charEnc = "UTF-8";
    }
    return new MarkdownFormatter().extractTitleFromMarkdown(
          readWholeEntry(jar, entry),
          charEnc);
  }

  private static JarEntry findSource(JarFile jar, String file) {
    if (file.endsWith(".html")) {
      int d = file.lastIndexOf('.');
      return jar.getJarEntry(file.substring(0, d) + ".md");
    }
    return null;
  }

  private static boolean exists(JarEntry entry) {
    return entry != null && entry.getSize() > 0;
  }

  private void sendMarkdownAsHtml(JarFile jar, JarEntry entry,
      String pluginName, ResourceKey key, HttpServletResponse res)
      throws IOException {
    byte[] rawmd = readWholeEntry(jar, entry);
    String encoding = null;
    Attributes atts = entry.getAttributes();
    if (atts != null) {
      encoding = Strings.emptyToNull(atts.getValue("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);
  }

  private void sendResource(JarFile jar, JarEntry entry,
      ResourceKey key, HttpServletResponse res)
      throws IOException {
    byte[] data = null;
    if (entry.getSize() <= SMALL_RESOURCE) {
      data = readWholeEntry(jar, entry);
    }

    String contentType = null;
    String charEnc = null;
    Attributes atts = entry.getAttributes();
    if (atts != null) {
      contentType = Strings.emptyToNull(atts.getValue("Content-Type"));
      charEnc = Strings.emptyToNull(atts.getValue("Character-Encoding"));
    }
    if (contentType == null) {
      contentType = mimeUtil.getMimeType(entry.getName(), data).toString();
    }

    long time = entry.getTime();
    if (0 < time) {
      res.setDateHeader("Last-Modified", time);
    }
    res.setHeader("Content-Length", Long.toString(entry.getSize()));
    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 {
      InputStream in = jar.getInputStream(entry);
      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(JarFile jar, JarEntry entry)
      throws IOException {
    byte[] data = new byte[(int) entry.getSize()];
    InputStream in = jar.getInputStream(entry);
    try {
      IO.readFully(in, data, 0, data.length);
    } finally {
      in.close();
    }
    return data;
  }

  private static String extractName(HttpServletRequest req) {
    String path = req.getPathInfo();
    if (Strings.isNullOrEmpty(path) || "/".equals(path)) {
      return "";
    }
    int s = path.indexOf('/', 1);
    return 0 <= s ? path.substring(1, s) : path.substring(1);
  }

  static void noCache(HttpServletResponse res) {
    res.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
    res.setHeader("Pragma", "no-cache");
    res.setHeader("Cache-Control", "no-cache, must-revalidate");
    res.setHeader("Content-Disposition", "attachment");
  }

  private static class PluginHolder {
    final Plugin plugin;
    final GuiceFilter filter;

    PluginHolder(Plugin plugin, GuiceFilter filter) {
      this.plugin = plugin;
      this.filter = filter;
    }
  }

  private static class WrappedRequest extends HttpServletRequestWrapper {
    private final String contextPath;

    WrappedRequest(HttpServletRequest req, String contextPath) {
      super(req);
      this.contextPath = contextPath;
    }

    @Override
    public String getContextPath() {
      return contextPath;
    }

    @Override
    public String getServletPath() {
      return ((HttpServletRequest) getRequest()).getRequestURI();
    }
  }
}
