// 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;
      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();
    }
  }
}
