// Copyright (C) 2011 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.pgm.rules;

import com.google.gerrit.common.Version;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlecode.prolog_cafe.compiler.Compiler;
import com.googlecode.prolog_cafe.exceptions.CompileException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;

/**
 * Helper class for Rulec: does the actual prolog -> java src -> class -> jar work Finds rules.pl in
 * refs/meta/config branch Creates rules-(sha1 of rules.pl).jar in (site-path)/cache/rules
 */
public class PrologCompiler implements Callable<PrologCompiler.Status> {
  public interface Factory {
    PrologCompiler create(Repository git);
  }

  public enum Status {
    NO_RULES,
    COMPILED
  }

  private final Path ruleDir;
  private final Repository git;

  @Inject
  PrologCompiler(
      @GerritServerConfig Config config, SitePaths site, @Assisted Repository gitRepository) {
    Path cacheDir = site.resolve(config.getString("cache", null, "directory"));
    ruleDir = cacheDir != null ? cacheDir.resolve("rules") : null;
    git = gitRepository;
  }

  @Override
  public Status call() throws IOException, CompileException {
    ObjectId metaConfig = git.resolve(RefNames.REFS_CONFIG);
    if (metaConfig == null) {
      return Status.NO_RULES;
    }

    ObjectId rulesId = git.resolve(metaConfig.name() + ":rules.pl");
    if (rulesId == null) {
      return Status.NO_RULES;
    }

    if (ruleDir == null) {
      throw new CompileException("Caching not enabled");
    }
    Files.createDirectories(ruleDir);

    File tempDir = File.createTempFile("GerritCodeReview_", ".rulec");
    if (!tempDir.delete() || !tempDir.mkdir()) {
      throw new IOException("Cannot create " + tempDir);
    }
    try {
      // Try to make the directory accessible only by this process.
      // This may help to prevent leaking rule data to outsiders.
      tempDir.setReadable(true, true);
      tempDir.setWritable(true, true);
      tempDir.setExecutable(true, true);

      compileProlog(rulesId, tempDir);
      compileJava(tempDir);

      Path jarPath = ruleDir.resolve("rules-" + rulesId.getName() + ".jar");
      List<String> classFiles = getRelativePaths(tempDir, ".class");
      createJar(jarPath, classFiles, tempDir, metaConfig, rulesId);

      return Status.COMPILED;
    } finally {
      deleteAllFiles(tempDir);
    }
  }

  /** Creates a copy of rules.pl and compiles it into Java sources. */
  private void compileProlog(ObjectId prolog, File tempDir) throws IOException, CompileException {
    File tempRules = copyToTempFile(prolog, tempDir);
    try {
      Compiler comp = new Compiler();
      comp.prologToJavaSource(tempRules.getPath(), tempDir.getPath());
    } finally {
      tempRules.delete();
    }
  }

  private File copyToTempFile(ObjectId blobId, File tempDir)
      throws IOException, FileNotFoundException, MissingObjectException {
    // Any leak of tmp caused by this method failing will be cleaned
    // up by our caller when tempDir is recursively deleted.
    File tmp = File.createTempFile("rules", ".pl", tempDir);
    try (OutputStream out = Files.newOutputStream(tmp.toPath())) {
      git.open(blobId).copyTo(out);
    }
    return tmp;
  }

  /** Compile java src into java .class files */
  private void compileJava(File tempDir) throws IOException, CompileException {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    if (compiler == null) {
      throw new CompileException("JDK required (running inside of JRE)");
    }

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
    try (StandardJavaFileManager fileManager =
        compiler.getStandardFileManager(diagnostics, null, null)) {
      Iterable<? extends JavaFileObject> compilationUnits =
          fileManager.getJavaFileObjectsFromFiles(getAllFiles(tempDir, ".java"));
      ArrayList<String> options = new ArrayList<>();
      String classpath = getMyClasspath();
      if (classpath != null) {
        options.add("-classpath");
        options.add(classpath);
      }
      options.add("-d");
      options.add(tempDir.getPath());
      JavaCompiler.CompilationTask task =
          compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
      if (!task.call()) {
        Locale myLocale = Locale.getDefault();
        StringBuilder msg = new StringBuilder();
        msg.append("Cannot compile to Java bytecode:");
        for (Diagnostic<? extends JavaFileObject> err : diagnostics.getDiagnostics()) {
          msg.append('\n');
          msg.append(err.getKind());
          msg.append(": ");
          if (err.getSource() != null) {
            msg.append(err.getSource().getName());
          }
          msg.append(':');
          msg.append(err.getLineNumber());
          msg.append(": ");
          msg.append(err.getMessage(myLocale));
        }
        throw new CompileException(msg.toString());
      }
    }
  }

  private String getMyClasspath() {
    StringBuilder cp = new StringBuilder();
    appendClasspath(cp, getClass().getClassLoader());
    return 0 < cp.length() ? cp.toString() : null;
  }

  private void appendClasspath(StringBuilder cp, ClassLoader classLoader) {
    if (classLoader.getParent() != null) {
      appendClasspath(cp, classLoader.getParent());
    }
    if (classLoader instanceof URLClassLoader) {
      for (URL url : ((URLClassLoader) classLoader).getURLs()) {
        if ("file".equals(url.getProtocol())) {
          if (0 < cp.length()) {
            cp.append(File.pathSeparatorChar);
          }
          cp.append(url.getPath());
        }
      }
    }
  }

  /** Takes compiled prolog .class files, puts them into the jar file. */
  private void createJar(
      Path archiveFile, List<String> toBeJared, File tempDir, ObjectId metaConfig, ObjectId rulesId)
      throws IOException {
    long now = TimeUtil.nowMs();
    Manifest mf = new Manifest();
    mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
    mf.getMainAttributes().putValue("Built-by", "Gerrit Code Review " + Version.getVersion());
    if (git.getDirectory() != null) {
      mf.getMainAttributes().putValue("Source-Repository", git.getDirectory().getPath());
    }
    mf.getMainAttributes().putValue("Source-Commit", metaConfig.name());
    mf.getMainAttributes().putValue("Source-Blob", rulesId.name());

    Path tmpjar = Files.createTempFile(archiveFile.getParent(), ".rulec_", ".jar");
    try (OutputStream stream = Files.newOutputStream(tmpjar);
        JarOutputStream out = new JarOutputStream(stream, mf)) {
      byte[] buffer = new byte[10240];
      // TODO: fixify this loop
      for (String path : toBeJared) {
        JarEntry jarAdd = new JarEntry(path);
        File f = new File(tempDir, path);
        jarAdd.setTime(now);
        out.putNextEntry(jarAdd);
        if (f.isFile()) {
          try (InputStream in = Files.newInputStream(f.toPath())) {
            while (true) {
              int nRead = in.read(buffer, 0, buffer.length);
              if (nRead <= 0) {
                break;
              }
              out.write(buffer, 0, nRead);
            }
          }
        }
        out.closeEntry();
      }
    }

    try {
      Files.move(tmpjar, archiveFile);
    } catch (IOException e) {
      throw new IOException("Cannot replace " + archiveFile, e);
    }
  }

  private List<File> getAllFiles(File dir, String extension) throws IOException {
    ArrayList<File> fileList = new ArrayList<>();
    getAllFiles(dir, extension, fileList);
    return fileList;
  }

  private void getAllFiles(File dir, String extension, List<File> fileList) throws IOException {
    for (File f : listFiles(dir)) {
      if (f.getName().endsWith(extension)) {
        fileList.add(f);
      }
      if (f.isDirectory()) {
        getAllFiles(f, extension, fileList);
      }
    }
  }

  private List<String> getRelativePaths(File dir, String extension) throws IOException {
    ArrayList<String> pathList = new ArrayList<>();
    getRelativePaths(dir, extension, "", pathList);
    return pathList;
  }

  private static void getRelativePaths(
      File dir, String extension, String path, List<String> pathList) throws IOException {
    for (File f : listFiles(dir)) {
      if (f.getName().endsWith(extension)) {
        pathList.add(path + f.getName());
      }
      if (f.isDirectory()) {
        getRelativePaths(f, extension, path + f.getName() + "/", pathList);
      }
    }
  }

  private static void deleteAllFiles(File dir) throws IOException {
    for (File f : listFiles(dir)) {
      if (f.isDirectory()) {
        deleteAllFiles(f);
      } else {
        f.delete();
      }
    }
    dir.delete();
  }

  private static File[] listFiles(File dir) throws IOException {
    File[] files = dir.listFiles();
    if (files == null) {
      throw new IOException("Failed to list directory: " + dir);
    }
    return files;
  }
}
