// 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 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;

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;

/**
 * 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.5.0)
  private static int[] MINIMUM_BAZEL_VERSION = {0, 5, 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",
        "--override_repository=local_eclipse_aspect=" + aspectLocation.getWorkspaceDirectory(),
        "--aspects=@local_eclipse_aspect" + 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 File execRoot;

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

    private BazelInstance(File workspaceRoot)
        throws IOException, InterruptedException, BazelNotFoundException {
      this.workspaceRoot = workspaceRoot;
      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").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")
          .addAll(buildOptions).add(extraArgs).addAll(targets).build());
    }

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

}
