// Copyright 2019 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.runtime.commands;

import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Comparator.comparing;
import static java.util.Map.Entry.comparingByKey;

import com.google.common.base.Functions;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
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.commands.ConfigCommand.ConfigOptions;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
import com.google.devtools.build.lib.skyframe.SkyFunctions;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** Handles the 'config' command on the Blaze command line. */
@Command(
    name = "config",
    builds = true,
    inherits = {BuildCommand.class},
    options = {ConfigOptions.class},
    usesConfigurationOptions = true,
    shortDescription = "Displays details of configurations.",
    allowResidue = true,
    completion = "string",
    hidden = true,
    help = "resource:config.txt")
public class ConfigCommand implements BlazeCommand {

  /** Options for the "config" command. */
  public static class ConfigOptions extends OptionsBase {
    @Option(
        name = "dump_all",
        defaultValue = "false",
        documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
        effectTags = {OptionEffectTag.AFFECTS_OUTPUTS},
        help = "If set, dump all known configurations instead of just the ids.")
    public boolean dumpAll;
  }

  @Override
  public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
    ImmutableMap<String, BuildConfiguration> configurations = findConfigurations(env);

    try (PrintWriter writer =
        new PrintWriter(
            new OutputStreamWriter(env.getReporter().getOutErr().getOutputStream(), UTF_8))) {

      if (options.getResidue().isEmpty()) {
        if (options.getOptions(ConfigOptions.class).dumpAll) {
          return reportAllConfigurations(writer, env);
        } else {
          return reportConfigurationIds(writer, configurations.keySet());
        }
      }

      if (options.getResidue().size() == 1) {
        String configHash = options.getResidue().get(0);
        env.getReporter()
            .handle(Event.info(String.format("Displaying config with id %s", configHash)));

        BuildConfiguration config = configurations.get(configHash);
        if (config == null) {
          env.getReporter()
              .handle(Event.error(String.format("No configuration found with id: %s", configHash)));
          return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
        }

        StringBuilder sb = new StringBuilder();
        config.describe(sb);
        writer.print(sb.toString());

        return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
      } else if (options.getResidue().size() == 2) {
        String configHash1 = options.getResidue().get(0);
        String configHash2 = options.getResidue().get(1);
        env.getReporter()
            .handle(
                Event.info(
                    String.format(
                        "Displaying diff between configs" + " %s and" + " %s",
                        configHash1, configHash2)));

        BuildConfiguration config1 = configurations.get(configHash1);
        if (config1 == null) {
          env.getReporter()
              .handle(
                  Event.error(String.format("No configuration found with id: %s", configHash1)));
          return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
        }
        BuildConfiguration config2 = configurations.get(configHash2);
        if (config2 == null) {
          env.getReporter()
              .handle(
                  Event.error(String.format("No configuration found with id: %s", configHash2)));
          return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
        }

        writer.printf(
            "Displaying diff between configs" + " %s and" + " %s\n", configHash1, configHash2);
        Table<Class<? extends FragmentOptions>, String, Pair<Object, Object>> diffs =
            diffConfigurations(config1, config2);
        writer.print(describeConfigDiff(diffs));
        return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
      } else {
        env.getReporter().handle(Event.error("Too many config ids."));
        return BlazeCommandResult.exitCode(ExitCode.COMMAND_LINE_ERROR);
      }
    }
  }

  private ImmutableMap<String, BuildConfiguration> findConfigurations(CommandEnvironment env) {
    InMemoryMemoizingEvaluator evaluator =
        (InMemoryMemoizingEvaluator)
            env.getRuntime().getWorkspace().getSkyframeExecutor().getEvaluatorForTesting();
    return evaluator.getDoneValues().entrySet().stream()
        .filter(e -> SkyFunctions.BUILD_CONFIGURATION.equals(e.getKey().functionName()))
        .map(Map.Entry::getValue)
        .map(v -> (BuildConfigurationValue) v)
        .map(BuildConfigurationValue::getConfiguration)
        .collect(
            toImmutableMap(
                BuildConfiguration::checksum, Functions.identity(), (config1, config2) -> config1));
  }

  private BlazeCommandResult reportAllConfigurations(PrintWriter writer, CommandEnvironment env) {
    InMemoryMemoizingEvaluator evaluator =
        (InMemoryMemoizingEvaluator)
            env.getRuntime().getWorkspace().getSkyframeExecutor().getEvaluatorForTesting();
    ImmutableMap<BuildConfigurationValue.Key, BuildConfigurationValue> configs =
        evaluator.getDoneValues().entrySet().stream()
            .filter(e -> SkyFunctions.BUILD_CONFIGURATION.equals(e.getKey().functionName()))
            .collect(
                toImmutableMap(
                    e -> (BuildConfigurationValue.Key) e.getKey(),
                    e -> (BuildConfigurationValue) e.getValue()));

    for (Map.Entry<BuildConfigurationValue.Key, BuildConfigurationValue> entry :
        configs.entrySet()) {
      writer.print("BuildConfigurationValue.Key: ");
      writer.println(entry.getKey().toString());

      writer.print("BuildConfigurationValue:\n");
      StringBuilder sb = new StringBuilder();
      entry.getValue().getConfiguration().describe(sb);
      writer.print(sb.toString());
    }
    return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
  }

  private BlazeCommandResult reportConfigurationIds(
      PrintWriter writer, ImmutableSet<String> configurationIds) {
    writer.println("Available configurations:");
    writer.println(configurationIds.stream().collect(Collectors.joining("\n")));

    return BlazeCommandResult.exitCode(ExitCode.SUCCESS);
  }

  /**
   * Starlark options don't have configuration fragments. This is just to keep their output
   * consistent with native options, i.e. to include "user-defined" section in the output list.
   */
  private static class UserDefinedFragment extends FragmentOptions {
    // Intentionally empty: we read the actual options directly from BuildOptions.
  }

  private Table<Class<? extends FragmentOptions>, String, Pair<Object, Object>> diffConfigurations(
      BuildConfiguration config1, BuildConfiguration config2) {
    Table<Class<? extends FragmentOptions>, String, Pair<Object, Object>> diffs =
        HashBasedTable.create();

    for (Class<? extends FragmentOptions> fragment :
        Sets.union(
            config1.getOptions().getFragmentClasses(), config2.getOptions().getFragmentClasses())) {
      FragmentOptions options1 = config1.getOptions().get(fragment);
      FragmentOptions options2 = config2.getOptions().get(fragment);
      diffs.row(fragment).putAll(diffOptions(fragment, options1, options2));
    }

    diffs.row(UserDefinedFragment.class).putAll(diffStarlarkOptions(config1, config2));
    return diffs;
  }

  private static Map<String, Pair<Object, Object>> diffOptions(
      Class<? extends FragmentOptions> fragment,
      @Nullable FragmentOptions options1,
      @Nullable FragmentOptions options2) {
    Map<String, Pair<Object, Object>> diffs = new HashMap<>();

    for (OptionDefinition option : OptionsParser.getOptionDefinitions(fragment)) {
      Object value1 = options1 == null ? null : options1.getValueFromDefinition(option);
      Object value2 = options2 == null ? null : options2.getValueFromDefinition(option);

      if (!Objects.equals(value1, value2)) {
        diffs.put(option.getOptionName(), Pair.of(value1, value2));
      }
    }

    return diffs;
  }

  private static Map<String, Pair<Object, Object>> diffStarlarkOptions(
      BuildConfiguration config1, BuildConfiguration config2) {
    Map<Label, Object> starlarkOptions1 = config1.getOptions().getStarlarkOptions();
    Map<Label, Object> starlarkOptions2 = config2.getOptions().getStarlarkOptions();
    Map<String, Pair<Object, Object>> diffs = new HashMap<>();
    for (Label option : Sets.union(starlarkOptions1.keySet(), starlarkOptions2.keySet())) {
      Object value1 = starlarkOptions1.get(option);
      Object value2 = starlarkOptions2.get(option);
      if (!Objects.equals(value1, value2)) {
        diffs.put(option.toString(), Pair.of(value1, value2));
      }
    }
    return diffs;
  }

  private static String describeConfigDiff(
      Table<Class<? extends FragmentOptions>, String, Pair<Object, Object>> diff) {
    StringBuilder sb = new StringBuilder();

    diff.rowKeySet().stream()
        .sorted(comparing(Class::getName))
        .forEach(fragmentClass -> displayFragmentDiff(fragmentClass, diff.row(fragmentClass), sb));

    return sb.toString();
  }

  private static void displayFragmentDiff(
      Class<? extends FragmentOptions> fragmentClass,
      Map<String, Pair<Object, Object>> diff,
      StringBuilder sb) {
    sb.append("Fragment ").append(fragmentClass.getName()).append(" {\n");
    diff.entrySet().stream()
        .sorted(comparingByKey())
        .forEach(
            e ->
                sb.append("  ")
                    .append(e.getKey())
                    .append(": ")
                    .append(e.getValue().getFirst())
                    .append(", ")
                    .append(e.getValue().getSecond())
                    .append("\n"));
    sb.append("}\n");
  }
}
