// Copyright 2018 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.build.lib.bazel.commands;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.analysis.NoBuildRequestFinishedEvent;
import com.google.devtools.build.lib.bazel.repository.RepositoryOrderEvent;
import com.google.devtools.build.lib.bazel.repository.skylark.SkylarkRepositoryFunction;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler.ResolvedEvent;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.WorkspaceFileValue;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
import com.google.devtools.build.lib.rules.repository.ResolvedHashesFunction;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandResult;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.KeepGoingOption;
import com.google.devtools.build.lib.runtime.LoadingPhaseThreadsOption;
import com.google.devtools.build.lib.skyframe.PackageLookupValue;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/** Syncs all repositories specified in the workspace file */
@Command(
    name = SyncCommand.NAME,
    options = {
      PackageCacheOptions.class,
      KeepGoingOption.class,
      LoadingPhaseThreadsOption.class,
      SyncOptions.class
    },
    help = "resource:sync.txt",
    shortDescription = "Syncs all repositories specified in the workspace file",
    allowResidue = false)
public final class SyncCommand implements BlazeCommand {
  public static final String NAME = "sync";

  static final ImmutableSet<String> WHITELISTED_NATIVE_RULES =
      ImmutableSet.<String>of("local_repository", "new_local_repository");

  @Override
  public void editOptions(OptionsParser optionsParser) {}

  private static void reportError(CommandEnvironment env, EvaluationResult<SkyValue> value) {
    if (value.getError().getException() != null) {
      env.getReporter().handle(Event.error(value.getError().getException().getMessage()));
    } else {
      env.getReporter().handle(Event.error(value.getError().toString()));
    }
  }

  @Override
  public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
    ExitCode exitCode = ExitCode.SUCCESS;

    try {
      env.getReporter()
          .post(
              new NoBuildEvent(
                  env.getCommandName(),
                  env.getCommandStartTime(),
                  true,
                  true,
                  env.getCommandId().toString()));
      env.setupPackageCache(options);
      SkyframeExecutor skyframeExecutor = env.getSkyframeExecutor();

      SyncOptions syncOptions = options.getOptions(SyncOptions.class);
      if (syncOptions.configure) {
        skyframeExecutor.injectExtraPrecomputedValues(
            ImmutableList.of(
                PrecomputedValue.injected(
                    RepositoryDelegatorFunction.DEPENDENCY_FOR_UNCONDITIONAL_CONFIGURING,
                    env.getCommandId().toString())));
      } else {
        skyframeExecutor.injectExtraPrecomputedValues(
            ImmutableList.of(
                PrecomputedValue.injected(
                    RepositoryDelegatorFunction.DEPENDENCY_FOR_UNCONDITIONAL_FETCHING,
                    env.getCommandId().toString())));
      }

      // Obtain the key for the top-level WORKSPACE file
      SkyKey packageLookupKey = PackageLookupValue.key(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER);
      LoadingPhaseThreadsOption threadsOption = options.getOptions(LoadingPhaseThreadsOption.class);
      EvaluationContext evaluationContext =
          EvaluationContext.newBuilder()
              .setNumThreads(threadsOption.threads)
              .setEventHander(env.getReporter())
              .build();
      EvaluationResult<SkyValue> packageLookupValue =
          skyframeExecutor.prepareAndGet(ImmutableSet.of(packageLookupKey), evaluationContext);
      if (packageLookupValue.hasError()) {
        reportError(env, packageLookupValue);
        env.getReporter()
            .post(
                new NoBuildRequestFinishedEvent(
                    ExitCode.ANALYSIS_FAILURE, env.getRuntime().getClock().currentTimeMillis()));
        return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
      }
      RootedPath workspacePath =
          ((PackageLookupValue) packageLookupValue.get(packageLookupKey))
              .getRootedPath(LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER);
      SkyKey workspace = WorkspaceFileValue.key(workspacePath);

      // read and evaluate the WORKSPACE file to its end
      ImmutableList.Builder<String> repositoryOrder = new ImmutableList.Builder<>();
      Set<String> namesSeen = new HashSet<>();
      WorkspaceFileValue fileValue = null;
      while (workspace != null) {
        EvaluationResult<SkyValue> value =
            skyframeExecutor.prepareAndGet(ImmutableSet.of(workspace), evaluationContext);
        if (value.hasError()) {
          reportError(env, value);
          env.getReporter()
              .post(
                  new NoBuildRequestFinishedEvent(
                      ExitCode.ANALYSIS_FAILURE, env.getRuntime().getClock().currentTimeMillis()));
          return BlazeCommandResult.exitCode(ExitCode.ANALYSIS_FAILURE);
        }
        fileValue = (WorkspaceFileValue) value.get(workspace);
        for (Rule rule : fileValue.getPackage().getTargets(Rule.class)) {
          String name = rule.getName();
          if (!namesSeen.contains(name)) {
            repositoryOrder.add(name);
            namesSeen.add(name);
          }
        }
        workspace = fileValue.next();
      }
      env.getReporter()
          .post(
              genericArgsCall(
                  "register_toolchains", fileValue.getPackage().getRegisteredToolchains()));
      env.getReporter()
          .post(
              genericArgsCall(
                  "register_execution_platforms",
                  fileValue.getPackage().getRegisteredExecutionPlatforms()));
      env.getReporter().post(new RepositoryOrderEvent(repositoryOrder.build()));

      // take all skylark workspace rules and get their values
      ImmutableSet.Builder<SkyKey> repositoriesToFetch = new ImmutableSet.Builder<>();
      for (Rule rule : fileValue.getPackage().getTargets(Rule.class)) {
        if (rule.getRuleClass().equals("bind")) {
          // The bind rule is special in that the name is not that of an external repository.
          // Moreover, it is not affected by the invalidation mechanism as there is nothing to
          // fetch anyway. So the only task remaining is to record the use of "bind" for whoever
          // collects resolved information.
          env.getReporter().post(resolveBind(rule));
        } else if (shouldSync(rule, syncOptions.configure)) {
          // TODO(aehlig): avoid the detour of serializing and then parsing the repository name
          try {
            repositoriesToFetch.add(
                RepositoryDirectoryValue.key(RepositoryName.create("@" + rule.getName())));
          } catch (LabelSyntaxException e) {
            env.getReporter()
                .handle(
                    Event.error(
                        "Internal error queuing "
                            + rule.getName()
                            + " to fetch: "
                            + e.getMessage()));
            env.getReporter()
                .post(
                    new NoBuildRequestFinishedEvent(
                        ExitCode.BLAZE_INTERNAL_ERROR,
                        env.getRuntime().getClock().currentTimeMillis()));
            return BlazeCommandResult.exitCode(ExitCode.BLAZE_INTERNAL_ERROR);
          }
        }
      }
      EvaluationResult<SkyValue> fetchValue;
      fetchValue = skyframeExecutor.prepareAndGet(repositoriesToFetch.build(), evaluationContext);
      if (fetchValue.hasError()) {
        reportError(env, fetchValue);
        exitCode = ExitCode.ANALYSIS_FAILURE;
      }
    } catch (InterruptedException e) {
      exitCode = ExitCode.INTERRUPTED;
    } catch (AbruptExitException e) {
      env.getReporter().handle(Event.error(e.getMessage()));
      exitCode = ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
    }
    env.getReporter()
        .post(
            new NoBuildRequestFinishedEvent(
                exitCode, env.getRuntime().getClock().currentTimeMillis()));
    return BlazeCommandResult.exitCode(exitCode);
  }

  private static boolean shouldSync(Rule rule, boolean configure) {
    if (!rule.getRuleClassObject().getWorkspaceOnly()) {
      // We should only sync workspace rules
      return false;
    }
    if (configure) {
      // If this is only a configure run, only sync Starlark rules that
      // declare themselves as configure-like.
      return SkylarkRepositoryFunction.isConfigureRule(rule);
    }
    if (rule.getRuleClassObject().isSkylark()) {
      // Skylark rules are all whitelisted
      return true;
    }
    return WHITELISTED_NATIVE_RULES.contains(rule.getRuleClassObject().getName());
  }

  private static ResolvedEvent resolveBind(Rule rule) {
    String name = rule.getName();
    Object actual = rule.getAttributeContainer().getAttr("actual");
    String nativeCommand =
        "bind(name = "
            + Printer.getPrinter().repr(name)
            + ", actual = "
            + Printer.getWorkspacePrettyPrinter().repr(actual)
            + ")";

    return new ResolvedEvent() {
      @Override
      public String getName() {
        return name;
      }

      @Override
      public Object getResolvedInformation() {
        return ImmutableMap.<String, Object>builder()
            .put(ResolvedHashesFunction.ORIGINAL_RULE_CLASS, "bind")
            .put(
                ResolvedHashesFunction.ORIGINAL_ATTRIBUTES,
                ImmutableMap.<String, Object>of("name", name, "actual", actual))
            .put(ResolvedHashesFunction.NATIVE, nativeCommand)
            .build();
      }
    };
  }

  private static ResolvedEvent genericArgsCall(String ruleName, List<String> args) {
    // For the name attribute we are in a slightly tricky situation, as the ResolvedEvents are
    // designed for external repositories and hence are indexted by their unique
    // names. Technically, however, things like the list of toolchains are not associated with any
    // external repository (but still a workspace command); so we take a name that syntactially can
    // never be the name of a repository, as it starts with a '//'.
    String name = "//external/" + ruleName;
    StringBuilder nativeCommandBuilder = new StringBuilder().append(ruleName).append("(");
    nativeCommandBuilder.append(
        args.stream()
            .map(arg -> Printer.getPrinter().repr(arg).toString())
            .collect(Collectors.joining(", ")));
    nativeCommandBuilder.append(")");
    String nativeCommand = nativeCommandBuilder.toString();

    return new ResolvedEvent() {
      @Override
      public String getName() {
        return name;
      }

      @Override
      public Object getResolvedInformation() {
        return ImmutableMap.<String, Object>builder()
            .put(ResolvedHashesFunction.ORIGINAL_RULE_CLASS, ruleName)
            .put(
                ResolvedHashesFunction.ORIGINAL_ATTRIBUTES,
                // The original attributes are a bit of a problem, as the arguments to
                // the rule do not at all look like those of a repository rule:
                // they're all positional, and, in particular, there is no keyword argument
                // called "name". A lot of uses of the resolved file, however, blindly assume
                // that "name" is always part of the original arguments; so we provide our
                // fake name here as well, and the actual arguments under the keyword "*args",
                // which hopefully reminds everyone inspecting the file of the actual syntax of
                // that rule. Note that the original arguments are always ignored when bazel uses
                // a resolved file instead of a workspace file.
                ImmutableMap.<String, Object>of("name", name, "*args", args))
            .put(ResolvedHashesFunction.NATIVE, nativeCommand)
            .build();
      }
    };
  }
}
