// Copyright 2016 The Bazel Authors. 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.devtools.bazel.e4b.command;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.bazel.e4b.command.CommandConsole.CommandConsoleFactory;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Main utility to call bazel commands, wrapping its input and output to the message console.
 */
public class BazelCommand {

  private static Joiner NEW_LINE_JOINER = Joiner.on("\n");
  private static Pattern VERSION_PATTERN =
      Pattern.compile("^([0-9]+)\\.([0-9]+)\\.([0-9]+)([^0-9].*)?$");

  // Minimum bazel version needed to work with this plugin (currently 0.4.0)
  private static int[] MINIMUM_BAZEL_VERSION = {0, 4, 0};

  private static enum ConsoleType {
    NO_CONSOLE, SYSTEM, WORKSPACE
  }

  private final BazelAspectLocation aspectLocation;
  private final CommandConsoleFactory consoleFactory;

  private final List<String> buildOptions;
  private final List<String> aspectOptions;

  private final Map<File, BazelInstance> instances = new HashMap<>();
  private String bazel = null;

  /**
   * Create a {@link BazelCommand} object, providing the implementation for locating aspect and
   * getting console streams.
   */
  public BazelCommand(BazelAspectLocation aspectLocation, CommandConsoleFactory consoleFactory) {
    this.aspectLocation = aspectLocation;
    this.consoleFactory = consoleFactory;
    this.buildOptions =
        ImmutableList.of("--watchfs", "--aspects=" + aspectLocation.getAspectLabel());
    this.aspectOptions = ImmutableList.<String>builder().addAll(buildOptions).add("-k",
        "--output_groups=ide-info-text,ide-resolve,-_,-defaults", "--experimental_show_artifacts")
        .build();
  }

  private String getBazelPath() throws BazelNotFoundException {
    if (bazel == null) {
      throw new BazelNotFoundException.BazelNotSetException();
    }
    return bazel;
  }

  /**
   * Set the path to the Bazel binary.
   */
  public synchronized void setBazelPath(String bazel) {
    this.bazel = bazel;
  }

  /**
   * Check the version of Bazel: throws an exception if the version is incorrect or the path does
   * not point to a Bazel binary.
   */
  public void checkVersion(String bazel) throws BazelNotFoundException {
    File path = new File(bazel);
    if (!path.exists() || !path.canExecute()) {
      throw new BazelNotFoundException.BazelNotExecutableException();
    }
    try {
      Command command = Command.builder(consoleFactory).setConsoleName(null)
          .setDirectory(aspectLocation.getWorkspaceDirectory()).addArguments(bazel, "version")
          .setStdoutLineSelector((s) -> s.startsWith("Build label:") ? s.substring(13) : null)
          .build();
      if (command.run() != 0) {
        throw new BazelNotFoundException.BazelNotExecutableException();
      }
      List<String> result = command.getSelectedOutputLines();
      if (result.size() != 1) {
        throw new BazelNotFoundException.BazelTooOldException("unknown");
      }
      String version = result.get(0);
      Matcher versionMatcher = VERSION_PATTERN.matcher(version);
      if (versionMatcher == null || !versionMatcher.matches()) {
        throw new BazelNotFoundException.BazelTooOldException(version);
      }
      int[] versionNumbers = {Integer.parseInt(versionMatcher.group(1)),
          Integer.parseInt(versionMatcher.group(2)), Integer.parseInt(versionMatcher.group(3))};
      if (compareVersion(versionNumbers, MINIMUM_BAZEL_VERSION) < 0) {
        throw new BazelNotFoundException.BazelTooOldException(version);
      }
    } catch (IOException | InterruptedException e) {
      throw new BazelNotFoundException.BazelNotExecutableException();
    }
  }

  private static int compareVersion(int[] version1, int[] version2) {
    for (int i = 0; i < Math.min(version1.length, version2.length); i++) {
      if (version1[i] < version2[i]) {
        return -1;
      } else if (version1[i] > version2[i]) {
        return 1;
      }
    }
    return Integer.compare(version1.length, version2.length);
  }

  /**
   * Returns a {@link BazelInstance} for the given directory. It looks for the enclosing workspace
   * and returns the instance that correspond to it. If not in a workspace, returns null.
   * 
   * @throws BazelNotFoundException
   */
  public BazelInstance getInstance(File directory)
      throws IOException, InterruptedException, BazelNotFoundException {
    File workspaceRoot = getWorkspaceRoot(directory);
    if (workspaceRoot == null) {
      return null;
    }
    if (!instances.containsKey(workspaceRoot)) {
      instances.put(workspaceRoot, new BazelInstance(workspaceRoot));
    }
    return instances.get(workspaceRoot);
  }

  /**
   * An instance of the Bazel interface for a specific workspace. Provides means to query Bazel on
   * this workspace.
   */
  public class BazelInstance {
    private final File workspaceRoot;
    private final String packagePath;
    private final File execRoot;

    private final Map<String, ImmutableMap<String, IdeBuildInfo>> buildInfoCache = new HashMap<>();

    private BazelInstance(File workspaceRoot)
        throws IOException, InterruptedException, BazelNotFoundException {
      this.workspaceRoot = workspaceRoot;
      this.packagePath = String.join("", runBazel("info", "package_path")) + ":"
          + aspectLocation.getWorkspaceDirectory().toString();
      this.execRoot = new File(String.join("", runBazel("info", "execution_root")));
    }

    /**
     * Returns the list of targets present in the BUILD files for the given sub-directories.
     * 
     * @throws BazelNotFoundException
     */
    public synchronized List<String> listTargets(File... directories)
        throws IOException, InterruptedException, BazelNotFoundException {
      StringBuilder builder = new StringBuilder();
      for (File f : directories) {
        builder.append(f.toURI().relativize(workspaceRoot.toURI()).getPath()).append("/... ");
      }
      return runBazel("query", builder.toString());
    }

    private synchronized List<String> runBazel(String... args)
        throws IOException, InterruptedException, BazelNotFoundException {
      return runBazel(ImmutableList.<String>builder().add(args).build());
    }

    private synchronized List<String> runBazel(List<String> args)
        throws IOException, InterruptedException, BazelNotFoundException {
      return BazelCommand.this.runBazelAndGetOuputLines(ConsoleType.WORKSPACE, workspaceRoot, args);
    }

    /**
     * Returns the IDE build information from running the aspect over the given list of targets. The
     * result is a list of of path to the output artifact created by the build.
     * 
     * @throws BazelNotFoundException
     */
    private synchronized List<String> buildIdeInfo(Collection<String> targets)
        throws IOException, InterruptedException, BazelNotFoundException {
      return BazelCommand.this.runBazelAndGetErrorLines(ConsoleType.WORKSPACE, workspaceRoot,
          ImmutableList.<String>builder().add("build").add("--package_path", packagePath)
              .addAll(aspectOptions).addAll(targets).build(),
          // Strip out the artifact list, keeping the e4b-build.json files.
          t -> t.startsWith(">>>") ? (t.endsWith(".e4b-build.json") ? t.substring(3) : "") : null);
    }

    /**
     * Runs the analysis of the given list of targets using the IDE build information aspect and
     * returns a map of {@link IdeBuildInfo}-s (key is the label of the target) containing the
     * parsed form of the JSON file created by the aspect.
     *
     * <p>
     * This method cache it results and won't recompute a previously computed version unless
     * {@link #markAsDirty()} has been called in between.
     * 
     * @throws BazelNotFoundException
     */
    public synchronized Map<String, IdeBuildInfo> getIdeInfo(Collection<String> targets)
        throws IOException, InterruptedException, BazelNotFoundException {
      String key = NEW_LINE_JOINER.join(targets);
      if (!buildInfoCache.containsKey(key)) {
        buildInfoCache.put(key, IdeBuildInfo.getInfo(buildIdeInfo(targets)));
      }
      return buildInfoCache.get(key);
    }

    /**
     * Clear the IDE build information cache. This cache is filled upon request and never emptied
     * unless we call that function.
     *
     * <p>
     * This function totally clear the cache and that might leads to useless rebuilds when several
     * eclipse project points to the same workspace but that is a rare case.
     */
    public synchronized void markAsDirty() {
      buildInfoCache.clear();
    }

    /**
     * Build a list of targets in the current workspace.
     * 
     * @throws BazelNotFoundException
     */
    public synchronized int build(List<String> targets, String... extraArgs)
        throws IOException, InterruptedException, BazelNotFoundException {
      return BazelCommand.this.runBazel(workspaceRoot,
          ImmutableList.<String>builder().add("build", "--package_path", packagePath)
              .addAll(buildOptions).add(extraArgs).addAll(targets).build());
    }

    /**
     * Run test on a list of targets in the current workspace.
     * 
     * @throws BazelNotFoundException
     */
    public synchronized int tests(List<String> targets, String... extraArgs)
        throws IOException, InterruptedException, BazelNotFoundException {
      return BazelCommand.this.runBazel(workspaceRoot,
          ImmutableList.<String>builder().add("test").add("--package_path", packagePath)
              .addAll(buildOptions).add(extraArgs).addAll(targets).build());
    }

    /**
     * Returns the workspace root corresponding to this object.
     */
    public File getWorkspaceRoot() {
      return workspaceRoot;
    }

    /**
     * Returns the execution root of the current workspace.
     */
    public File getExecRoot() {
      return execRoot;
    }

    /**
     * Gives a list of target completions for the given beginning string. The result is the list of
     * possible completion for a target pattern starting with string.
     * 
     * @throws BazelNotFoundException
     */
    public List<String> complete(String string)
        throws IOException, InterruptedException, BazelNotFoundException {
      if (string.equals("/") || string.isEmpty()) {
        return ImmutableList.of("//");
      } else if (string.contains(":")) {
        // complete targets using `bazel query`
        int idx = string.indexOf(':');
        final String packageName = string.substring(0, idx);
        final String targetPrefix = string.substring(idx + 1);
        ImmutableList.Builder<String> builder = ImmutableList.builder();
        builder.addAll(
            BazelCommand.this.runBazelAndGetOuputLines(ConsoleType.NO_CONSOLE, workspaceRoot,
                ImmutableList.<String>builder().add("query", packageName + ":*").build(), line -> {
                  int i = line.indexOf(':');
                  String s = line.substring(i + 1);
                  return !s.isEmpty() && s.startsWith(targetPrefix) ? (packageName + ":" + s)
                      : null;
                }));
        if ("all".startsWith(targetPrefix)) {
          builder.add(packageName + ":all");
        }
        if ("*".startsWith(targetPrefix)) {
          builder.add(packageName + ":*");
        }
        return builder.build();
      } else {
        // complete packages
        int lastSlash = string.lastIndexOf('/');
        final String prefix = lastSlash > 0 ? string.substring(0, lastSlash + 1) : "";
        final String suffix = lastSlash > 0 ? string.substring(lastSlash + 1) : string;
        final String directory = (prefix.isEmpty() || prefix.equals("//")) ? ""
            : prefix.substring(string.startsWith("//") ? 2 : 0, prefix.length() - 1);
        File file = directory.isEmpty() ? workspaceRoot : new File(workspaceRoot, directory);
        ImmutableList.Builder<String> builder = ImmutableList.builder();
        File[] files = file.listFiles((f) -> {
          // Only give directories whose name starts with suffix...
          return f.getName().startsWith(suffix) && f.isDirectory()
          // ...that does not start with '.'...
              && !f.getName().startsWith(".")
          // ...and is not a Bazel convenience link
              && (!file.equals(workspaceRoot) || !f.getName().startsWith("bazel-"));
        });
        if (files != null) {
          for (File d : files) {
            builder.add(prefix + d.getName() + "/");
            if (new File(d, "BUILD").exists()) {
              builder.add(prefix + d.getName() + ":");
            }
          }
        }
        if ("...".startsWith(suffix)) {
          builder.add(prefix + "...");
        }
        return builder.build();
      }
    }
  }

  private File getWorkspaceRoot(File directory)
      throws IOException, InterruptedException, BazelNotFoundException {
    List<String> result = runBazelAndGetOuputLines(ConsoleType.SYSTEM, directory,
        ImmutableList.of("info", "workspace"));
    if (result.size() > 0) {
      return new File(result.get(0));
    }
    return null;
  }

  private List<String> runBazelAndGetOuputLines(ConsoleType type, File directory, List<String> args)
      throws IOException, InterruptedException, BazelNotFoundException {
    return runBazelAndGetOuputLines(type, directory, args, (t) -> t);
  }

  private synchronized List<String> runBazelAndGetOuputLines(ConsoleType type, File directory,
      List<String> args, Function<String, String> selector)
      throws IOException, InterruptedException, BazelNotFoundException {
    Command command = Command.builder(consoleFactory)
        .setConsoleName(getConsoleName(type, directory)).setDirectory(directory)
        .addArguments(getBazelPath()).addArguments(args).setStdoutLineSelector(selector).build();
    if (command.run() == 0) {
      return command.getSelectedOutputLines();
    }
    return ImmutableList.of();
  }

  private synchronized List<String> runBazelAndGetErrorLines(ConsoleType type, File directory,
      List<String> args, Function<String, String> selector)
      throws IOException, InterruptedException, BazelNotFoundException {
    Command command = Command.builder(consoleFactory)
        .setConsoleName(getConsoleName(type, directory)).setDirectory(directory)
        .addArguments(getBazelPath()).addArguments(args).setStderrLineSelector(selector).build();
    if (command.run() == 0) {
      return command.getSelectedErrorLines();
    }
    return ImmutableList.of();
  }

  private synchronized int runBazel(ConsoleType type, File directory, List<String> args,
      OutputStream stdout, OutputStream stderr)
      throws IOException, InterruptedException, BazelNotFoundException {
    return Command.builder(consoleFactory).setConsoleName(getConsoleName(type, directory))
        .setDirectory(directory).addArguments(getBazelPath()).addArguments(args)
        .setStandardOutput(stdout).setStandardError(stderr).build().run();
  }

  private int runBazel(File directory, List<String> args)
      throws IOException, InterruptedException, BazelNotFoundException {
    return runBazel(ConsoleType.WORKSPACE, directory, args, null, null);
  }

  private String getConsoleName(ConsoleType type, File directory) {
    switch (type) {
      case SYSTEM:
        return "Bazel [system]";
      case WORKSPACE:
        return "Bazel [" + directory.toString() + "]";
      case NO_CONSOLE:
      default:
        return null;
    }
  }

}
