// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.gitiles.doc;

import static com.google.gitiles.doc.MarkdownUtil.getInnerText;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.gitiles.GitilesView;
import com.google.gitiles.ThreadSafePrettifyParser;
import com.google.gitiles.doc.html.HtmlBuilder;
import com.google.template.soy.data.SanitizedContent;
import com.google.template.soy.shared.restricted.EscapingConventions.FilterImageDataUri;
import com.google.template.soy.shared.restricted.EscapingConventions.FilterNormalizeUri;

import org.commonmark.ext.gfm.strikethrough.Strikethrough;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TableBody;
import org.commonmark.ext.gfm.tables.TableCell;
import org.commonmark.ext.gfm.tables.TableHead;
import org.commonmark.ext.gfm.tables.TableRow;
import org.commonmark.node.Block;
import org.commonmark.node.BlockQuote;
import org.commonmark.node.BulletList;
import org.commonmark.node.Code;
import org.commonmark.node.CustomBlock;
import org.commonmark.node.CustomNode;
import org.commonmark.node.Document;
import org.commonmark.node.Emphasis;
import org.commonmark.node.FencedCodeBlock;
import org.commonmark.node.HardLineBreak;
import org.commonmark.node.Heading;
import org.commonmark.node.HtmlBlock;
import org.commonmark.node.HtmlInline;
import org.commonmark.node.Image;
import org.commonmark.node.IndentedCodeBlock;
import org.commonmark.node.Link;
import org.commonmark.node.ListBlock;
import org.commonmark.node.ListItem;
import org.commonmark.node.Node;
import org.commonmark.node.OrderedList;
import org.commonmark.node.Paragraph;
import org.commonmark.node.SoftLineBreak;
import org.commonmark.node.StrongEmphasis;
import org.commonmark.node.Text;
import org.commonmark.node.ThematicBreak;
import org.commonmark.node.Visitor;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevTree;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

import prettify.parser.Prettify;
import syntaxhighlight.ParseResult;

/**
 * Formats parsed Markdown AST into HTML.
 * <p>
 * Callers must create a new instance for each document.
 */
public class MarkdownToHtml implements Visitor {
  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {
    private String requestUri;
    private GitilesView view;
    private MarkdownConfig config;
    private String filePath;
    private ObjectReader reader;
    private RevTree root;

    Builder() {}

    public Builder setRequestUri(@Nullable String uri) {
      requestUri = uri;
      return this;
    }

    public Builder setGitilesView(@Nullable GitilesView view) {
      this.view = view;
      return this;
    }

    public Builder setConfig(@Nullable MarkdownConfig config) {
      this.config = config;
      return this;
    }

    public Builder setFilePath(@Nullable String filePath) {
      this.filePath = Strings.emptyToNull(filePath);
      return this;
    }

    public Builder setReader(ObjectReader reader) {
      this.reader = reader;
      return this;
    }

    public Builder setRootTree(RevTree tree) {
      this.root = tree;
      return this;
    }

    public MarkdownToHtml build() {
      return new MarkdownToHtml(this);
    }
  }

  private final HtmlBuilder html = new HtmlBuilder();
  private final TocFormatter toc = new TocFormatter(html, 3);
  private final String requestUri;
  private final GitilesView view;
  private final MarkdownConfig config;
  private final String filePath;
  private final ImageLoader imageLoader;
  private boolean outputNamedAnchor = true;

  private MarkdownToHtml(Builder b) {
    requestUri = b.requestUri;
    view = b.view;
    config = b.config;
    filePath = b.filePath;
    imageLoader = newImageLoader(b);
  }

  private static ImageLoader newImageLoader(Builder b) {
    if (b.reader != null && b.view != null && b.config != null && b.root != null) {
      return new ImageLoader(b.reader, b.view, b.config, b.root);
    }
    return null;
  }

  /** Render the document AST to sanitized HTML. */
  public SanitizedContent toSoyHtml(Node node) {
    if (node == null) {
      return null;
    }

    toc.setRoot(node);
    node.accept(this);
    return html.toSoy();
  }

  @Override
  public void visit(Document node) {
    visitChildren(node);
  }

  private void visit(BlockNote node) {
    html.open("div").attribute("class", node.getClassName());
    Node f = node.getFirstChild();
    if (f == node.getLastChild() && f instanceof Paragraph) {
      // Avoid <p> inside <div> if there is only one <p>.
      visitChildren(f);
    } else {
      visitChildren(node);
    }
    html.close("div");
  }

  private void visit(MultiColumnBlock node) {
    html.open("div").attribute("class", "cols");
    visitChildren(node);
    html.close("div");
  }

  private void visit(MultiColumnBlock.Column node) {
    if (1 <= node.span && node.span <= MultiColumnBlock.GRID_WIDTH) {
      html.open("div").attribute("class", "col-" + node.span);
      visitChildren(node);
      html.close("div");
    }
  }

  private void visit(IframeBlock node) {
    if (HtmlBuilder.isValidHttpUri(node.src)
        && HtmlBuilder.isValidCssDimension(node.height)
        && HtmlBuilder.isValidCssDimension(node.width)
        && config != null
        && config.isIFrameAllowed(node.src)) {
      html.open("iframe")
          .attribute("src", node.src)
          .attribute("height", node.height)
          .attribute("width", node.width);
      if (!node.border) {
        html.attribute("class", "noborder");
      }
      html.close("iframe");
    }
  }

  @Override
  public void visit(Heading node) {
    outputNamedAnchor = false;
    String tag = "h" + node.getLevel();
    html.open(tag);
    String id = toc.idFromHeader(node);
    if (id != null) {
      html.open("a")
          .attribute("class", "h")
          .attribute("name", id)
          .attribute("href", "#" + id)
          .open("span")
          .close("span")
          .close("a");
    }
    visitChildren(node);
    html.close(tag);
    outputNamedAnchor = true;
  }

  private void visit(NamedAnchor node) {
    if (outputNamedAnchor) {
      html.open("a").attribute("name", node.getName()).close("a");
    }
  }

  @Override
  public void visit(Paragraph node) {
    if (isInTightList(node)) {
      // Avoid unnecessary <p> tags within <ol><li> structures.
      visitChildren(node);
    } else {
      wrapChildren("p", node);
    }
  }

  private static boolean isInTightList(Paragraph c) {
    Block b = c.getParent(); // b is probably a ListItem
    if (b != null) {
      Block a = b.getParent();
      return a instanceof ListBlock && ((ListBlock) a).isTight();
    }
    return false;
  }

  @Override
  public void visit(BlockQuote node) {
    wrapChildren("blockquote", node);
  }

  @Override
  public void visit(OrderedList node) {
    html.open("ol");
    if (node.getStartNumber() != 1) {
      html.attribute("start", Integer.toString(node.getStartNumber()));
    }
    visitChildren(node);
    html.close("ol");
  }

  @Override
  public void visit(BulletList node) {
    wrapChildren("ul", node);
  }

  @Override
  public void visit(ListItem node) {
    wrapChildren("li", node);
  }

  @Override
  public void visit(FencedCodeBlock node) {
    codeInPre(node.getInfo(), node.getLiteral());
  }

  @Override
  public void visit(IndentedCodeBlock node) {
    codeInPre(null, node.getLiteral());
  }

  private void codeInPre(String lang, String text) {
    html.open("pre").attribute("class", "code");
    text = printLeadingBlankLines(text);
    List<ParseResult> parsed = parse(lang, text);
    if (parsed != null) {
      int last = 0;
      for (ParseResult r : parsed) {
        span(null, text, last, r.getOffset());
        last = r.getOffset() + r.getLength();
        span(r.getStyleKeysString(), text, r.getOffset(), last);
      }
      if (last < text.length()) {
        span(null, text, last, text.length());
      }
    } else {
      html.appendAndEscape(text);
    }
    html.close("pre");
  }

  private String printLeadingBlankLines(String text) {
    int i = 0;
    while (i < text.length() && text.charAt(i) == '\n') {
      html.open("br");
      i++;
    }
    return text.substring(i);
  }

  private void span(String classes, String s, int start, int end) {
    if (end - start > 0) {
      if (Strings.isNullOrEmpty(classes)) {
        classes = Prettify.PR_PLAIN;
      }
      html.open("span").attribute("class", classes);
      html.appendAndEscape(s.substring(start, end));
      html.close("span");
    }
  }

  private List<ParseResult> parse(String lang, String text) {
    if (Strings.isNullOrEmpty(lang)) {
      return null;
    }
    try {
      return ThreadSafePrettifyParser.INSTANCE.parse(lang, text);
    } catch (StackOverflowError e) {
      return null;
    }
  }

  @Override
  public void visit(Code node) {
    html.open("code").appendAndEscape(node.getLiteral()).close("code");
  }

  @Override
  public void visit(Emphasis node) {
    wrapChildren("em", node);
  }

  @Override
  public void visit(StrongEmphasis node) {
    wrapChildren("strong", node);
  }

  @Override
  public void visit(Link node) {
    html.open("a")
        .attribute("href", href(node.getDestination()))
        .attribute("title", node.getTitle());
    visitChildren(node);
    html.close("a");
  }

  @VisibleForTesting
  String href(String target) {
    if (target.startsWith("#") || HtmlBuilder.isValidHttpUri(target)) {
      return target;
    }

    String anchor = "";
    int hash = target.indexOf('#');
    if (hash >= 0) {
      anchor = target.substring(hash);
      target = target.substring(0, hash);
    }

    String dest = PathResolver.resolve(filePath, target);
    if (dest == null || view == null) {
      return FilterNormalizeUri.INSTANCE.getInnocuousOutput();
    }

    GitilesView.Builder b;
    if (view.getType() == GitilesView.Type.ROOTED_DOC) {
      b = GitilesView.rootedDoc();
    } else {
      b = GitilesView.path();
    }
    dest = b.copyFrom(view).setPathPart(dest).build().toUrl();

    return PathResolver.relative(requestUri, dest) + anchor;
  }

  @Override
  public void visit(Image node) {
    html.open("img")
        .attribute("src", image(node.getDestination()))
        .attribute("title", node.getTitle())
        .attribute("alt", getInnerText(node));
  }

  String image(String dest) {
    if (HtmlBuilder.isValidHttpUri(dest) || HtmlBuilder.isImageDataUri(dest)) {
      return dest;
    } else if (imageLoader != null) {
      return imageLoader.inline(filePath, dest);
    }
    return FilterImageDataUri.INSTANCE.getInnocuousOutput();
  }

  public void visit(TableBlock node) {
    wrapChildren("table", node);
  }

  private void visit(TableRow node) {
    wrapChildren("tr", node);
  }

  private void visit(TableCell cell) {
    String tag = cell.isHeader() ? "th" : "td";
    html.open(tag);
    TableCell.Alignment alignment = cell.getAlignment();
    if (alignment != null) {
      html.attribute("align", toHtml(alignment));
    }
    visitChildren(cell);
    html.close(tag);
  }

  private static String toHtml(TableCell.Alignment alignment) {
    switch (alignment) {
      case LEFT:
        return "left";
      case CENTER:
        return "center";
      case RIGHT:
        return "right";
      default:
        throw new IllegalArgumentException("unsupported alignment " + alignment);
    }
  }

  private void visit(SmartQuoted node) {
    switch (node.getType()) {
      case DOUBLE:
        html.entity("&ldquo;");
        visitChildren(node);
        html.entity("&rdquo;");
        break;
      case SINGLE:
        html.entity("&lsquo;");
        visitChildren(node);
        html.entity("&rsquo;");
        break;
      default:
        throw new IllegalArgumentException("unsupported quote " + node.getType());
    }
  }

  private static final Pattern PRETTY = Pattern.compile("('|[.]{3}|-{2,3})");

  @Override
  public void visit(Text node) {
    String text = node.getLiteral();
    Matcher pretty = PRETTY.matcher(text);
    int i = 0;
    while (pretty.find()) {
      int s = pretty.start();
      if (i < s) {
        html.appendAndEscape(text.substring(i, s));
      }
      switch (pretty.group(0)) {
        case "'":
          html.entity("&rsquo;");
          break;
        case "...":
          html.entity("&hellip;");
          break;
        case "--":
          html.entity("&ndash;");
          break;
        case "---":
          html.entity("&mdash;");
          break;
      }
      i = pretty.end();
    }
    if (i < text.length()) {
      html.appendAndEscape(text.substring(i));
    }
  }

  @Override
  public void visit(SoftLineBreak node) {
    html.space();
  }

  @Override
  public void visit(HardLineBreak node) {
    html.open("br");
  }

  @Override
  public void visit(ThematicBreak thematicBreak) {
    html.open("hr");
  }

  @Override
  public void visit(HtmlInline node) {
    // Discard all HTML.
  }

  @Override
  public void visit(HtmlBlock node) {
    // Discard all HTML.
  }

  private void wrapChildren(String tag, Node node) {
    html.open(tag);
    visitChildren(node);
    html.close(tag);
  }

  private void visitChildren(Node node) {
    for (Node c = node.getFirstChild(); c != null; c = c.getNext()) {
      c.accept(this);
    }
  }

  @Override
  public void visit(CustomNode node) {
    if (node instanceof NamedAnchor) {
      visit((NamedAnchor) node);
    } else if (node instanceof SmartQuoted) {
      visit((SmartQuoted) node);
    } else if (node instanceof Strikethrough) {
      wrapChildren("del", node);
    } else if (node instanceof TableBody) {
      wrapChildren("tbody", node);
    } else if (node instanceof TableCell) {
      visit((TableCell) node);
    } else if (node instanceof TableHead) {
      wrapChildren("thead", node);
    } else if (node instanceof TableRow) {
      visit((TableRow) node);
    } else {
      throw new IllegalArgumentException("cannot render " + node.getClass());
    }
  }

  @Override
  public void visit(CustomBlock node) {
    if (node instanceof BlockNote) {
      visit((BlockNote) node);
    } else if (node instanceof IframeBlock) {
      visit((IframeBlock) node);
    } else if (node instanceof MultiColumnBlock) {
      visit((MultiColumnBlock) node);
    } else if (node instanceof MultiColumnBlock.Column) {
      visit((MultiColumnBlock.Column) node);
    } else if (node instanceof TableBlock) {
      visit((TableBlock) node);
    } else if (node instanceof TocBlock) {
      toc.format();
    } else {
      throw new IllegalArgumentException("cannot render " + node.getClass());
    }
  }
}
