// Copyright (C) 2013 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.asciidoctor;

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

import com.google.common.io.ByteStreams;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.AttributesBuilder;
import org.asciidoctor.Options;
import org.asciidoctor.OptionsBuilder;
import org.asciidoctor.SafeMode;
import org.asciidoctor.internal.JRubyAsciidoctor;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.ParserProperties;

public class AsciiDoctor {

  private static final String DOCTYPE = "article";
  private static final String ERUBY = "erb";
  private static final String REVNUMBER_NAME = "revnumber";

  @Option(name = "-b", usage = "set output format backend")
  private String backend = "html5";

  @Option(name = "-z", usage = "output zip file")
  private String zipFile;

  @Option(name = "--in-ext", usage = "extension for input files")
  private String inExt = ".txt";

  @Option(name = "--out-ext", usage = "extension for output files")
  private String outExt = ".html";

  @Option(name = "--base-dir", usage = "base directory")
  private File basedir;

  @Option(name = "--tmp", usage = "temporary output path")
  private File tmpdir;

  @Option(name = "--mktmp", usage = "create a temporary output path")
  private boolean mktmp;

  @Option(name = "-a", usage = "a list of attributes, in the form key or key=value pair")
  private List<String> attributes = new ArrayList<>();

  @Option(
      name = "--bazel",
      usage = "bazel mode: generate multiple output files instead of a single zip file")
  private boolean bazel;

  @Option(name = "--revnumber-file", usage = "the file contains revnumber string")
  private File revnumberFile;

  @Argument(usage = "input files")
  private List<String> inputFiles = new ArrayList<>();

  private String revnumber;

  public static String mapInFileToOutFile(String inFile, String inExt, String outExt) {
    String basename = new File(inFile).getName();
    if (basename.endsWith(inExt)) {
      basename = basename.substring(0, basename.length() - inExt.length());
    } else {
      // Strip out the last extension
      int pos = basename.lastIndexOf('.');
      if (pos > 0) {
        basename = basename.substring(0, pos);
      }
    }
    return basename + outExt;
  }

  private Options createOptions(File base, File outputFile) {
    OptionsBuilder optionsBuilder = OptionsBuilder.options();

    optionsBuilder
        .backend(backend)
        .docType(DOCTYPE)
        .eruby(ERUBY)
        .safe(SafeMode.UNSAFE)
        .baseDir(base)
        .toFile(outputFile);

    AttributesBuilder attributesBuilder = AttributesBuilder.attributes();
    attributesBuilder.attributes(getAttributes());
    if (revnumber != null) {
      attributesBuilder.attribute(REVNUMBER_NAME, revnumber);
    }
    optionsBuilder.attributes(attributesBuilder.get());

    return optionsBuilder.get();
  }

  private Map<String, Object> getAttributes() {
    Map<String, Object> attributeValues = new HashMap<>();

    for (String attribute : attributes) {
      int equalsIndex = attribute.indexOf('=');
      if (equalsIndex > -1) {
        String name = attribute.substring(0, equalsIndex);
        String value = attribute.substring(equalsIndex + 1);

        attributeValues.put(name, value);
      } else {
        attributeValues.put(attribute, "");
      }
    }

    return attributeValues;
  }

  private void invoke(String... parameters) throws IOException {
    CmdLineParser parser = new CmdLineParser(this, ParserProperties.defaults().withAtSyntax(false));
    try {
      parser.parseArgument(parameters);
      if (inputFiles.isEmpty()) {
        throw new IllegalArgumentException("asciidoctor: FAILED: input file missing");
      }
    } catch (CmdLineException | IllegalArgumentException e) {
      System.err.println(e.getMessage());
      parser.printUsage(System.err);
      System.exit(1);
      return;
    }

    if (revnumberFile != null) {
      try (BufferedReader reader = Files.newBufferedReader(revnumberFile.toPath(), UTF_8)) {
        revnumber = reader.readLine();
      }
    }

    if (mktmp) {
      tmpdir = Files.createTempDirectory("asciidoctor-").toFile();
    }

    if (bazel) {
      renderFiles(inputFiles, null);
    } else {
      try (ZipOutputStream zip = new ZipOutputStream(Files.newOutputStream(Path.of(zipFile)))) {
        renderFiles(inputFiles, zip);

        File[] cssFiles = tmpdir.listFiles((dir, name) -> name.endsWith(".css"));
        for (File css : cssFiles) {
          zipFile(css, css.getName(), zip);
        }
      }
    }
  }

  private void renderFiles(List<String> inputFiles, ZipOutputStream zip) throws IOException {
    Asciidoctor asciidoctor = JRubyAsciidoctor.create();
    for (String inputFile : inputFiles) {
      String outName = mapInFileToOutFile(inputFile, inExt, outExt);
      File out = bazel ? new File(outName) : new File(tmpdir, outName);
      if (!bazel) {
        out.getParentFile().mkdirs();
      }
      File input = new File(inputFile);
      Options options = createOptions(basedir != null ? basedir : input.getParentFile(), out);
      asciidoctor.renderFile(input, options);
      if (zip != null) {
        zipFile(out, outName, zip);
      }
    }
  }

  public static void zipFile(File file, String name, ZipOutputStream zip) throws IOException {
    zip.putNextEntry(new ZipEntry(name));
    try (InputStream input = Files.newInputStream(file.toPath())) {
      ByteStreams.copy(input, zip);
    }
    zip.closeEntry();
  }

  public static void main(String[] args) {
    try {
      new AsciiDoctor().invoke(args);
    } catch (IOException e) {
      System.err.println(e.getMessage());
      System.exit(1);
    }
  }
}
