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

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.analysis.AspectCollection;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.Dependency;
import com.google.devtools.build.lib.analysis.DependencyResolver;
import com.google.devtools.build.lib.analysis.DependencyResolver.InconsistentAspectOrderException;
import com.google.devtools.build.lib.analysis.PlatformSemantics;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.BuildOptions.OptionsDiff;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.analysis.config.FragmentClassSet;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.RuleTransitionFactory;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor;
import com.google.devtools.build.lib.query2.output.CqueryOptions;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.util.OrderedSetMultimap;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * Output formatter that prints {@link ConfigurationTransition} information for rule configured
 * targets in the results of a cquery call.
 */
public class TransitionsOutputFormatterCallback extends CqueryThreadsafeCallback {

  protected final BuildConfiguration hostConfiguration;

  private final HashMap<Label, Target> partialResultMap;
  @Nullable private final RuleTransitionFactory trimmingTransitionFactory;

  @Override
  public String getName() {
    return "transitions";
  }

  /**
   * @param accessor provider of query result configured targets.
   * @param hostConfiguration host configuration for this query.
   */
  TransitionsOutputFormatterCallback(
      Reporter reporter,
      CqueryOptions options,
      OutputStream out,
      SkyframeExecutor skyframeExecutor,
      TargetAccessor<ConfiguredTarget> accessor,
      BuildConfiguration hostConfiguration,
      @Nullable RuleTransitionFactory trimmingTransitionFactory) {
    super(reporter, options, out, skyframeExecutor, accessor);
    this.hostConfiguration = hostConfiguration;
    this.trimmingTransitionFactory = trimmingTransitionFactory;
    this.partialResultMap = Maps.newHashMap();
  }

  @Override
  public void processOutput(Iterable<ConfiguredTarget> partialResult)
      throws IOException, InterruptedException {
    CqueryOptions.Transitions verbosity = options.transitions;
    if (verbosity.equals(CqueryOptions.Transitions.NONE)) {
      reporter.handle(
          Event.error(
              "Instead of using --output=transitions, set the --transition flag"
                  + " explicitly to 'lite' or 'full'"));
      return;
    }
    partialResult.forEach(
        ct -> partialResultMap.put(ct.getLabel(), accessor.getTargetFromConfiguredTarget(ct)));
    for (ConfiguredTarget configuredTarget : partialResult) {
      Target target = partialResultMap.get(configuredTarget.getLabel());
      BuildConfiguration config =
          skyframeExecutor.getConfiguration(
              reporter, configuredTarget.getConfigurationKey());
      addResult(
          getRuleClassTransition(configuredTarget, target)
              + configuredTarget.getLabel()
              + " ("
              + (config != null && config.isHostConfiguration() ? "HOST" : config)
              + ")");
      if (!(configuredTarget instanceof RuleConfiguredTarget)) {
        continue;
      }
      OrderedSetMultimap<Attribute, Dependency> deps;
      ImmutableMap<Label, ConfigMatchingProvider> configConditions =
          ((RuleConfiguredTarget) configuredTarget).getConfigConditions();
      BuildOptions fromOptions = config.getOptions();
      try {
        // Note: Being able to pull the $toolchain attr unconditionally from the mapper relies on
        // the fact that {@link PlatformSemantics.TOOLCHAIN_ATTRS} exists in every rule.
        // Also, we don't actually use fromOptions in our implementation of DependencyResolver but
        // passing to avoid passing a null and since we have the information anyway.
        deps =
            new FormatterDependencyResolver(configuredTarget, reporter)
                .dependentNodeMap(
                    new TargetAndConfiguration(target, config),
                    hostConfiguration,
                    /*aspect=*/ null,
                    configConditions,
                    ImmutableSet.copyOf(
                        ConfiguredAttributeMapper.of(target.getAssociatedRule(), configConditions)
                            .get(PlatformSemantics.TOOLCHAINS_ATTR, BuildType.LABEL_LIST)),
                    fromOptions,
                    trimmingTransitionFactory);
      } catch (EvalException | InvalidConfigurationException | InconsistentAspectOrderException e) {
        throw new InterruptedException(e.getMessage());
      }
      for (Map.Entry<Attribute, Dependency> attributeAndDep : deps.entries()) {
        if (attributeAndDep.getValue().hasExplicitConfiguration()
            || attributeAndDep.getValue().getTransition() instanceof NoTransition) {
          continue;
        }
        List<BuildOptions> toOptions;
        Dependency dep = attributeAndDep.getValue();
        ConfigurationTransition transition = dep.getTransition();
        if (transition instanceof SplitTransition) {
          toOptions = ((SplitTransition) transition).split(fromOptions);
        } else if (transition instanceof PatchTransition) {
          toOptions = Collections.singletonList(((PatchTransition) transition).apply(fromOptions));
        } else {
          throw new IllegalStateException(
              "If this error is thrown, cquery needs to be updated to take into account non-Patch"
                  + " and non-Split Transitions");
        }
        String hostConfigurationChecksum = hostConfiguration.checksum();
        addResult(
            "  "
                .concat(attributeAndDep.getKey().getName())
                .concat("#")
                .concat(dep.getLabel().toString())
                .concat("#")
                .concat(dep.getTransition().getName())
                .concat(" ( -> ")
                .concat(
                    toOptions
                        .stream()
                        .map(
                            options -> {
                              String checksum = options.computeChecksum();
                              return checksum.equals(hostConfigurationChecksum) ? "HOST" : checksum;
                            })
                        .collect(Collectors.joining(", ")))
                .concat(")"));
        if (verbosity == CqueryOptions.Transitions.LITE) {
          continue;
        }
        OptionsDiff diff = new OptionsDiff();
        for (BuildOptions options : toOptions) {
          diff = BuildOptions.diff(diff, fromOptions, options);
        }
        diff.getPrettyPrintList().forEach(singleDiff -> addResult("    " + singleDiff));
      }
    }
  }

  private String getRuleClassTransition(ConfiguredTarget ct, Target target) {
    String output = "";
    if (ct instanceof RuleConfiguredTarget) {
      RuleTransitionFactory factory =
          target.getAssociatedRule().getRuleClassObject().getTransitionFactory();
      if (factory != null) {
        output =
            factory
                .buildTransitionFor(target.getAssociatedRule())
                .getClass()
                .getSimpleName()
                .concat(" -> ");
      }
    }
    return output;
  }

  private class FormatterDependencyResolver extends DependencyResolver {

    private ConfiguredTarget ct;
    private final ExtendedEventHandler eventHandler;

    private FormatterDependencyResolver(ConfiguredTarget ct, ExtendedEventHandler eventHandler) {
      this.ct = ct;
      this.eventHandler = eventHandler;
    }

    protected FormatterDependencyResolver setCt(ConfiguredTarget ct) {
      this.ct = ct;
      return this;
    }

    @Override
    protected void invalidVisibilityReferenceHook(TargetAndConfiguration node, Label label) {
      eventHandler.handle(
          Event.error(
              TargetUtils.getLocationMaybe(node.getTarget()),
              String.format(
                  "Label '%s' in visibility attribute does not refer to a package group", label)));
    }

    @Override
    protected void invalidPackageGroupReferenceHook(TargetAndConfiguration node, Label label) {
      eventHandler.handle(
          Event.error(
              TargetUtils.getLocationMaybe(node.getTarget()),
              String.format("label '%s' does not refer to a package group", label)));
    }

    @Override
    protected void missingEdgeHook(Target from, Label to, NoSuchThingException e) {
      eventHandler.handle(
          Event.error(
              "missing dependency from " + from.getLabel() + " to " + to + ": " + e.getMessage()));
    }

    @Override
    protected Target getTarget(Target from, Label label, NestedSetBuilder<Label> rootCauses)
        throws InterruptedException {
      return partialResultMap.get(label);
    }

    @Override
    protected List<BuildConfiguration> getConfigurations(
        FragmentClassSet fragments,
        Iterable<BuildOptions> buildOptions,
        BuildOptions defaultOptions) {
      Preconditions.checkArgument(
          ct.getConfigurationKey().getFragments().equals(fragments.fragmentClasses()),
          "Mismatch: %s %s",
          ct,
          fragments);
      Dependency asDep =
          Dependency.withTransitionAndAspects(
              ct.getLabel(), NoTransition.INSTANCE, AspectCollection.EMPTY);
      ImmutableList.Builder<BuildConfiguration> builder = ImmutableList.builder();
      for (BuildOptions options : buildOptions) {
        builder.add(
            Iterables.getOnlyElement(
                skyframeExecutor
                    .getConfigurations(eventHandler, options, ImmutableList.<Dependency>of(asDep))
                    .values()));
      }
      return builder.build();
    }
  }
}

