// 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());
    }

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

}
