// Copyright (C) 2008 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 com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.HostPageData;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gwtjsonrpc.server.RPCServletUtils;
import com.google.gwtexpui.linker.server.Permutation;
import com.google.gwtexpui.linker.server.PermutationSelector;
import com.google.gwtjsonrpc.server.JsonServlet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Sends the Gerrit host page to clients. */
@SuppressWarnings("serial")
@Singleton
public class HostPageServlet extends HttpServlet {
  private static final Logger log =
      LoggerFactory.getLogger(HostPageServlet.class);
  private static final boolean IS_DEV = Boolean.getBoolean("Gerrit.GwtDevMode");
  private static final String HPD_ID = "gerrit_hostpagedata";

  private final Provider<CurrentUser> currentUser;
  private final Provider<WebSession> session;
  private final GerritConfig config;
  private final HostPageData.Theme signedOutTheme;
  private final HostPageData.Theme signedInTheme;
  private final SitePaths site;
  private final Document template;
  private final String noCacheName;
  private final PermutationSelector selector;
  private final boolean refreshHeaderFooter;
  private volatile Page page;

  @Inject
  HostPageServlet(final Provider<CurrentUser> cu, final Provider<WebSession> w,
      final SitePaths sp, final ThemeFactory themeFactory,
      final GerritConfig gc, final ServletContext servletContext,
      @GerritServerConfig final Config cfg)
      throws IOException, ServletException {
    currentUser = cu;
    session = w;
    config = gc;
    signedOutTheme = themeFactory.getSignedOutTheme();
    signedInTheme = themeFactory.getSignedInTheme();
    site = sp;
    refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true);

    final String pageName = "HostPage.html";
    template = HtmlDomUtil.parseFile(getClass(), pageName);
    if (template == null) {
      throw new FileNotFoundException("No " + pageName + " in webapp");
    }

    if (HtmlDomUtil.find(template, "gerrit_module") == null) {
      throw new ServletException("No gerrit_module in " + pageName);
    }
    if (HtmlDomUtil.find(template, HPD_ID) == null) {
      throw new ServletException("No " + HPD_ID + " in " + pageName);
    }

    final String src = "gerrit/gerrit.nocache.js";
    selector = new PermutationSelector("gerrit");
    if (IS_DEV || !cfg.getBoolean("site", "checkUserAgent", true)) {
      noCacheName = src;
    } else {
      final Element devmode = HtmlDomUtil.find(template, "gerrit_gwtdevmode");
      if (devmode != null) {
        devmode.getParentNode().removeChild(devmode);
      }

      InputStream in = servletContext.getResourceAsStream("/" + src);
      if (in == null) {
        throw new IOException("No " + src + " in webapp root");
      }

      final MessageDigest md = Constants.newMessageDigest();
      try {
        try {
          final byte[] buf = new byte[1024];
          int n;
          while ((n = in.read(buf)) > 0) {
            md.update(buf, 0, n);
          }
        } finally {
          in.close();
        }
      } catch (IOException e) {
        throw new IOException("Failed reading " + src, e);
      }
      final String id = ObjectId.fromRaw(md.digest()).name();
      noCacheName = src + "?content=" + id;
      selector.init(servletContext);
    }

    page = new Page();
  }

  private void json(final Object data, final StringWriter w) {
    JsonServlet.defaultGsonBuilder().create().toJson(data, w);
  }

  private Page get() {
    Page p = page;
    if (refreshHeaderFooter && p.isStale()) {
      final Page newPage;
      try {
        newPage = new Page();
      } catch (IOException e) {
        log.error("Cannot refresh site header/footer", e);
        return p;
      }
      p = newPage;
      page = p;
    }
    return p;
  }

  @Override
  protected void doGet(final HttpServletRequest req,
      final HttpServletResponse rsp) throws IOException {
    final Page.Content page = get().get(select(req));
    final byte[] raw;

    final CurrentUser user = currentUser.get();
    if (user instanceof IdentifiedUser) {
      final StringWriter w = new StringWriter();
      w.write(HPD_ID + ".account=");
      json(((IdentifiedUser) user).getAccount(), w);
      w.write(";");

      w.write(HPD_ID + ".xsrfToken=");
      json(session.get().getToken(), w);
      w.write(";");

      w.write(HPD_ID + ".accountDiffPref=");
      json(((IdentifiedUser) user).getAccountDiffPreference(), w);
      w.write(";");

      w.write(HPD_ID + ".theme=");
      json(signedInTheme, w);
      w.write(";");

      final byte[] userData = w.toString().getBytes("UTF-8");
      raw = concat(page.part1, userData, page.part2);
    } else {
      raw = page.full;
    }

    final byte[] tosend;
    if (RPCServletUtils.acceptsGzipEncoding(req)) {
      rsp.setHeader("Content-Encoding", "gzip");
      tosend = raw == page.full ? page.full_gz : HtmlDomUtil.compress(raw);
    } else {
      tosend = raw;
    }

    rsp.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
    rsp.setHeader("Pragma", "no-cache");
    rsp.setHeader("Cache-Control", "no-cache, must-revalidate");
    rsp.setContentType("text/html");
    rsp.setCharacterEncoding(HtmlDomUtil.ENC);
    rsp.setContentLength(tosend.length);
    final OutputStream out = rsp.getOutputStream();
    try {
      out.write(tosend);
    } finally {
      out.close();
    }
  }

  private Permutation select(final HttpServletRequest req) {
    if ("0".equals(req.getParameter("s"))) {
      // If s=0 is used in the URL, the user has explicitly asked us
      // to not perform selection on the server side, perhaps due to
      // it incorrectly guessing their user agent.
      //
      return null;
    }
    return selector.select(req);
  }

  private static byte[] concat(byte[] p1, byte[] p2, byte[] p3) {
    final byte[] r = new byte[p1.length + p2.length + p3.length];
    int p = 0;
    p = append(p1, r, p);
    p = append(p2, r, p);
    p = append(p3, r, p);
    return r;
  }

  private static int append(byte[] src, final byte[] dst, int p) {
    System.arraycopy(src, 0, dst, p, src.length);
    return p + src.length;
  }

  private static class FileInfo {
    private final File path;
    private final long time;

    FileInfo(final File p) {
      path = p;
      time = path.lastModified();
    }

    boolean isStale() {
      return time != path.lastModified();
    }
  }

  private class Page {
    private final FileInfo css;
    private final FileInfo header;
    private final FileInfo footer;
    private final Map<Permutation, Content> permutations;

    Page() throws IOException {
      Document hostDoc = HtmlDomUtil.clone(template);

      css = injectCssFile(hostDoc, "gerrit_sitecss", site.site_css);
      header = injectXmlFile(hostDoc, "gerrit_header", site.site_header);
      footer = injectXmlFile(hostDoc, "gerrit_footer", site.site_footer);

      final HostPageData pageData = new HostPageData();
      pageData.config = config;

      final StringWriter w = new StringWriter();
      w.write("var " + HPD_ID + "=");
      json(pageData, w);
      w.write(";");

      final Element data = HtmlDomUtil.find(hostDoc, HPD_ID);
      asScript(data);
      data.appendChild(hostDoc.createTextNode(w.toString()));
      data.appendChild(hostDoc.createComment(HPD_ID));

      permutations = new HashMap<Permutation, Content>();
      for (Permutation p : selector.getPermutations()) {
        final Document d = HtmlDomUtil.clone(hostDoc);
        Element nocache = HtmlDomUtil.find(d, "gerrit_module");
        nocache.getParentNode().removeChild(nocache);
        p.inject(d);
        permutations.put(p, new Content(d));
      }

      Element nocache = HtmlDomUtil.find(hostDoc, "gerrit_module");
      asScript(nocache);
      nocache.setAttribute("src", noCacheName);
      permutations.put(null, new Content(hostDoc));
    }

    Content get(Permutation p) {
      Content c = permutations.get(p);
      if (c == null) {
        c = permutations.get(null);
      }
      return c;
    }

    boolean isStale() {
      return css.isStale() || header.isStale() || footer.isStale();
    }

    private void asScript(final Element scriptNode) {
      scriptNode.removeAttribute("id");
      scriptNode.setAttribute("type", "text/javascript");
      scriptNode.setAttribute("language", "javascript");
    }

    class Content {
      final byte[] part1;
      final byte[] part2;
      final byte[] full;
      final byte[] full_gz;

      Content(Document hostDoc) throws IOException {
        final String raw = HtmlDomUtil.toString(hostDoc);
        final int p = raw.indexOf("<!--" + HPD_ID);
        if (p < 0) {
          throw new IOException("No tag in transformed host page HTML");
        }
        part1 = raw.substring(0, p).getBytes("UTF-8");
        part2 = raw.substring(raw.indexOf('>', p) + 1).getBytes("UTF-8");

        final StringWriter w = new StringWriter();
        w.write(HPD_ID + ".theme=");
        json(signedOutTheme, w);
        w.write(";");

        final byte[] themeData = w.toString().getBytes("UTF-8");
        full = concat(part1, themeData, part2);
        full_gz = HtmlDomUtil.compress(full);
      }
    }

    private FileInfo injectCssFile(final Document hostDoc, final String id,
        final File src) throws IOException {
      final FileInfo info = new FileInfo(src);
      final Element banner = HtmlDomUtil.find(hostDoc, id);
      if (banner == null) {
        return info;
      }

      while (banner.getFirstChild() != null) {
        banner.removeChild(banner.getFirstChild());
      }

      String css = HtmlDomUtil.readFile(src.getParentFile(), src.getName());
      if (css == null) {
        banner.getParentNode().removeChild(banner);
        return info;
      }

      banner.removeAttribute("id");
      banner.appendChild(hostDoc.createCDATASection("\n" + css + "\n"));
      return info;
    }

    private FileInfo injectXmlFile(final Document hostDoc, final String id,
        final File src) throws IOException {
      final FileInfo info = new FileInfo(src);
      final Element banner = HtmlDomUtil.find(hostDoc, id);
      if (banner == null) {
        return info;
      }

      while (banner.getFirstChild() != null) {
        banner.removeChild(banner.getFirstChild());
      }

      Document html = HtmlDomUtil.parseFile(src);
      if (html == null) {
        banner.getParentNode().removeChild(banner);
        return info;
      }

      final Element content = html.getDocumentElement();
      banner.appendChild(hostDoc.importNode(content, true));
      return info;
    }
  }
}
