// 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.server.documentation;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.pegdown.Extensions.ALL;
import static org.pegdown.Extensions.HARDWRAPS;
import static org.pegdown.Extensions.SUPPRESS_ALL_HTML;

import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang.StringEscapeUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.pegdown.LinkRenderer;
import org.pegdown.PegDownProcessor;
import org.pegdown.ToHtmlSerializer;
import org.pegdown.ast.HeaderNode;
import org.pegdown.ast.Node;
import org.pegdown.ast.RootNode;
import org.pegdown.ast.TextNode;

public class MarkdownFormatter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String defaultCss;

  static {
    AtomicBoolean file = new AtomicBoolean();
    String src;
    try {
      src = readPegdownCss(file);
    } catch (IOException err) {
      logger.atWarning().withCause(err).log("Cannot load pegdown.css");
      src = "";
    }
    defaultCss = file.get() ? null : src;
  }

  private static String readCSS() {
    if (defaultCss != null) {
      return defaultCss;
    }
    try {
      return readPegdownCss(new AtomicBoolean());
    } catch (IOException err) {
      logger.atWarning().withCause(err).log("Cannot load pegdown.css");
      return "";
    }
  }

  private boolean suppressHtml;
  private String css;

  public MarkdownFormatter suppressHtml() {
    suppressHtml = true;
    return this;
  }

  public MarkdownFormatter setCss(String css) {
    this.css = StringEscapeUtils.escapeHtml(css);
    return this;
  }

  public byte[] markdownToDocHtml(String md, String charEnc) throws UnsupportedEncodingException {
    RootNode root = parseMarkdown(md);
    String title = findTitle(root);

    StringBuilder html = new StringBuilder();
    html.append("<html>");
    html.append("<head>");
    if (!Strings.isNullOrEmpty(title)) {
      html.append("<title>").append(title).append("</title>");
    }
    html.append("<style type=\"text/css\">\n");
    if (css != null) {
      html.append(css);
    } else {
      html.append(readCSS());
    }
    html.append("\n</style>");
    html.append("</head>");
    html.append("<body>\n");
    html.append(new ToHtmlSerializer(new LinkRenderer()).toHtml(root));
    html.append("\n</body></html>");
    return html.toString().getBytes(charEnc);
  }

  public String extractTitleFromMarkdown(byte[] data, String charEnc) {
    String md = RawParseUtils.decode(Charset.forName(charEnc), data);
    return findTitle(parseMarkdown(md));
  }

  private String findTitle(Node root) {
    if (root instanceof HeaderNode) {
      HeaderNode h = (HeaderNode) root;
      if (h.getLevel() == 1 && h.getChildren() != null && !h.getChildren().isEmpty()) {
        StringBuilder b = new StringBuilder();
        for (Node n : root.getChildren()) {
          if (n instanceof TextNode) {
            b.append(((TextNode) n).getText());
          }
        }
        return b.toString();
      }
    }

    for (Node n : root.getChildren()) {
      String title = findTitle(n);
      if (title != null) {
        return title;
      }
    }
    return null;
  }

  private RootNode parseMarkdown(String md) {
    int options = ALL & ~(HARDWRAPS);
    if (suppressHtml) {
      options |= SUPPRESS_ALL_HTML;
    }
    return new PegDownProcessor(options).parseMarkdown(md.toCharArray());
  }

  private static String readPegdownCss(AtomicBoolean file) throws IOException {
    String name = "pegdown.css";
    URL url = MarkdownFormatter.class.getResource(name);
    if (url == null) {
      throw new FileNotFoundException("Resource " + name);
    }
    file.set("file".equals(url.getProtocol()));
    try (InputStream in = url.openStream();
        TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(128 * 1024)) {
      tmp.copy(in);
      return new String(tmp.toByteArray(), UTF_8);
    }
  }
}
