// Copyright (C) 2014 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.googlesource.gerrit.plugins.xdocs;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.Weigher;
import com.google.common.collect.Maps;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.httpd.resources.Resource;
import com.google.gerrit.httpd.resources.SmallResource;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.xdocs.formatter.Formatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters;
import com.googlesource.gerrit.plugins.xdocs.formatter.Formatters.FormatterProvider;
import com.googlesource.gerrit.plugins.xdocs.formatter.StreamFormatter;
import com.googlesource.gerrit.plugins.xdocs.formatter.StringFormatter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.outerj.daisy.diff.HtmlCleaner;
import org.outerj.daisy.diff.XslFilter;
import org.outerj.daisy.diff.html.HTMLDiffer;
import org.outerj.daisy.diff.html.HtmlSaxDiffOutput;
import org.outerj.daisy.diff.html.TextNodeComparator;
import org.outerj.daisy.diff.html.dom.DomTreeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

@Singleton
public class XDocLoader extends CacheLoader<String, Resource> {
  private static final Logger log = LoggerFactory.getLogger(XDocLoader.class);

  private static final String DEFAULT_HOST = "review.example.com";

  private final GitRepositoryManager repoManager;
  private final Provider<String> webUrl;
  private final String pluginName;
  private final PluginConfigFactory cfgFactory;
  private final Formatters formatters;

  @Inject
  XDocLoader(
      GitRepositoryManager repoManager,
      @CanonicalWebUrl Provider<String> webUrl,
      @PluginName String pluginName,
      PluginConfigFactory cfgFactory,
      Formatters formatters) {
    this.repoManager = repoManager;
    this.webUrl = webUrl;
    this.pluginName = pluginName;
    this.cfgFactory = cfgFactory;
    this.formatters = formatters;
  }

  @Override
  public Resource load(String strKey) throws Exception {
    XDocResourceKey key = XDocResourceKey.fromString(strKey);
    try (Repository repo = repoManager.openRepository(key.getProject())) {
      FormatterProvider formatter = getFormatter(key.getFormatter());
      try (RevWalk rw = new RevWalk(repo)) {
        String html = null;
        if (key.getRevId() != null) {
          html = loadHtml(formatter, repo, rw, key, key.getRevId());
        }

        if (key.getDiffMode() != DiffMode.NO_DIFF) {
          String htmlB = loadHtml(formatter, repo, rw, key, checkRevId(key.getRevIdB()));
          if (html == null && htmlB == null) {
            throw new ResourceNotFoundException();
          }
          html = diffHtml(html, htmlB, key.getDiffMode());
        } else {
          if (html == null) {
            throw new ResourceNotFoundException();
          }
        }

        RevCommit commit =
            rw.parseCommit(MoreObjects.firstNonNull(key.getRevIdB(), key.getRevId()));
        return getAsHtmlResource(html, commit.getCommitTime());
      }
    } catch (ResourceNotFoundException e) {
      return Resource.NOT_FOUND;
    } catch (MethodNotAllowedException e) {
      return Resources.METHOD_NOT_ALLOWED;
    }
  }

  private FormatterProvider getFormatter(String formatterName) throws ResourceNotFoundException {
    FormatterProvider formatter = formatters.getByName(formatterName);
    if (formatter == null) {
      throw new ResourceNotFoundException();
    }
    return formatter;
  }

  private static ObjectId checkRevId(ObjectId revId) throws ResourceNotFoundException {
    if (revId == null) {
      throw new ResourceNotFoundException();
    }
    return revId;
  }

  private String loadHtml(
      FormatterProvider formatter, Repository repo, RevWalk rw, XDocResourceKey key, ObjectId revId)
      throws IOException, ResourceNotFoundException, MethodNotAllowedException, GitAPIException {
    RevCommit commit = rw.parseCommit(revId);
    RevTree tree = commit.getTree();
    try (TreeWalk tw = new TreeWalk(repo)) {
      tw.addTree(tree);
      tw.setRecursive(true);
      tw.setFilter(PathFilter.create(key.getResource()));
      if (!tw.next()) {
        return null;
      }
      ObjectId objectId = tw.getObjectId(0);
      ObjectLoader loader = repo.open(objectId);
      return getHtml(formatter, repo, loader, key.getProject(), key.getResource(), revId);
    }
  }

  private String getHtml(
      FormatterProvider formatter,
      Repository repo,
      ObjectLoader loader,
      Project.NameKey project,
      String path,
      ObjectId revId)
      throws MethodNotAllowedException, IOException, GitAPIException, ResourceNotFoundException {
    Formatter f = formatter.get();
    if (f instanceof StringFormatter) {
      return getHtml(formatter.getName(), (StringFormatter) f, repo, loader, project, path, revId);
    } else if (f instanceof StreamFormatter) {
      return getHtml(formatter.getName(), (StreamFormatter) f, repo, loader, project, path, revId);
    } else {
      log.error(String.format("Unsupported formatter: %s", formatter.getName()));
      throw new ResourceNotFoundException();
    }
  }

  private String getHtml(
      String formatterName,
      StringFormatter f,
      Repository repo,
      ObjectLoader loader,
      Project.NameKey project,
      String path,
      ObjectId revId)
      throws MethodNotAllowedException, IOException, GitAPIException {
    byte[] bytes = loader.getBytes(Integer.MAX_VALUE);
    boolean isBinary = RawText.isBinary(bytes);
    if (formatterName.equals(Formatters.RAW_FORMATTER) && isBinary) {
      throw new MethodNotAllowedException();
    }
    String raw = new String(bytes, UTF_8);
    String abbrRevId = getAbbrRevId(repo, revId);
    if (!isBinary) {
      raw = replaceMacros(repo, project, revId, abbrRevId, raw);
    }
    return f.format(
        project.get(), path, revId.getName(), abbrRevId, getFormatterConfig(formatterName), raw);
  }

  private String getHtml(
      String formatterName,
      StreamFormatter f,
      Repository repo,
      ObjectLoader loader,
      Project.NameKey project,
      String path,
      ObjectId revId)
      throws IOException {
    try (InputStream raw = loader.openStream()) {
      return f.format(
          project.get(),
          path,
          revId.getName(),
          getAbbrRevId(repo, revId),
          getFormatterConfig(formatterName),
          raw);
    }
  }

  private String diffHtml(String htmlA, String htmlB, DiffMode diffMode)
      throws IOException, TransformerConfigurationException, SAXException,
          ResourceNotFoundException {
    ByteArrayOutputStream htmlDiff = new ByteArrayOutputStream();

    SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance();
    TransformerHandler result = tf.newTransformerHandler();
    result.setResult(new StreamResult(htmlDiff));

    String htmlHeader = "com/googlesource/gerrit/plugins/xdocs/diff/htmlheader-";
    switch (diffMode) {
      case SIDEBYSIDE_A:
        htmlHeader += "sidebyside-a.xsl";
        break;
      case SIDEBYSIDE_B:
        htmlHeader += "sidebyside-b.xsl";
        break;
      case UNIFIED:
        htmlHeader += "unified.xsl";
        break;
      case NO_DIFF:
      default:
        log.error(String.format("Unsupported diff mode: %s", diffMode.name()));
        throw new ResourceNotFoundException();
    }

    ContentHandler postProcess = new XslFilter().xsl(result, htmlHeader);
    postProcess.startDocument();
    postProcess.startElement("", "diffreport", "diffreport", new AttributesImpl());
    postProcess.startElement("", "diff", "diff", new AttributesImpl());

    HtmlSaxDiffOutput output = new HtmlSaxDiffOutput(postProcess, "diff");
    HTMLDiffer differ = new HTMLDiffer(output);
    differ.diff(getComparator(htmlA), getComparator(htmlB));

    postProcess.endElement("", "diff", "diff");
    postProcess.endElement("", "diffreport", "diffreport");
    postProcess.endDocument();

    return fixStyles(htmlDiff.toString(UTF_8.name()));
  }

  /**
   * The daisydiff formatting may make inlined styles unparsable. Fix it:
   *
   * <ul>
   *   <li>Remove span element to highlight addition/deletion inside style elements.
   *   <li>Replace '&gt;' with '>'.
   * </ul>
   */
  private String fixStyles(String html) {
    Matcher m =
        Pattern.compile("(<style[a-zA-Z -=/\"]+>\n)<[a-zA-Z -=\"]+>(.*)</[a-z]+>(\n</style>)")
            .matcher(html);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      m.appendReplacement(sb, m.group(1) + m.group(2).replaceAll("&gt;", ">") + m.group(3));
    }
    m.appendTail(sb);
    return sb.toString();
  }

  private TextNodeComparator getComparator(String html) throws IOException, SAXException {
    InputSource source =
        new InputSource(new ByteArrayInputStream(Strings.nullToEmpty(html).getBytes(UTF_8)));
    DomTreeBuilder handler = new DomTreeBuilder();
    new HtmlCleaner().cleanAndParse(source, handler);
    return new TextNodeComparator(handler, Locale.US);
  }

  private ConfigSection getFormatterConfig(String formatterName) {
    XDocGlobalConfig cfg = new XDocGlobalConfig(cfgFactory.getGlobalPluginConfig(pluginName));
    return cfg.getFormatterConfig(formatterName);
  }

  private static String getAbbrRevId(Repository repo, ObjectId revId) throws IOException {
    try (ObjectReader reader = repo.newObjectReader()) {
      return reader.abbreviate(revId).name();
    }
  }

  private String replaceMacros(
      Repository repo, Project.NameKey project, ObjectId revId, String abbrRevId, String raw)
      throws GitAPIException, IOException {
    Map<String, String> macros = Maps.newHashMap();

    String url = webUrl.get();
    if (Strings.isNullOrEmpty(url)) {
      url = "http://" + DEFAULT_HOST + "/";
    }
    macros.put("URL", url);

    macros.put("PROJECT", project.get());
    macros.put("PROJECT_URL", url + "#/admin/projects/" + project.get());
    macros.put("REVISION", abbrRevId);
    try (Git git = new Git(repo)) {
      macros.put(
          "GIT_DESCRIPTION",
          MoreObjects.firstNonNull(git.describe().setTarget(revId).call(), abbrRevId));
    }

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

  private Resource getAsHtmlResource(String html, int lastModified) {
    return new SmallResource(html.getBytes(UTF_8))
        .setContentType("text/html")
        .setCharacterEncoding(UTF_8.name())
        .setLastModified(lastModified);
  }

  public static class Module extends CacheModule {
    static final String X_DOC_RESOURCES = "x_doc_resources";

    @Override
    protected void configure() {
      install(
          new CacheModule() {
            @Override
            protected void configure() {
              persist(X_DOC_RESOURCES, String.class, Resource.class)
                  .maximumWeight(2 << 20)
                  .weigher(XDocResourceWeigher.class)
                  .loader(XDocLoader.class);
            }
          });
    }
  }

  private static class XDocResourceWeigher implements Weigher<String, Resource> {
    @Override
    public int weigh(String key, Resource value) {
      return key.length() * 2 + value.weigh();
    }
  }
}
