// Copyright 2014 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.query.output;

import com.google.common.base.Ascii;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.compacthashset.CompactHashSet;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.License;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.query2.engine.OutputFormatterCallback;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment;
import com.google.devtools.build.lib.query2.engine.SynchronizedDelegatingOutputFormatterCallback;
import com.google.devtools.build.lib.query2.engine.ThreadSafeOutputFormatterCallback;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.BiPredicate;
import net.starlark.java.eval.Printer;
import net.starlark.java.eval.StarlarkThread;

/**
 * An output formatter that prints the generating rules using the syntax of the BUILD files. If
 * multiple targets are generated by the same rule, it is printed only once.
 */
public class BuildOutputFormatter extends AbstractUnorderedFormatter {

  /**
   * Generic interface for determining the possible values for a given attribute on a given rule, as
   * precisely as the implementation knows. For example, cquery knows which branch a <code>select
   * </code> takes, while query doesn't.
   */
  public interface AttributeReader {
    Iterable<Object> getPossibleValues(Rule rule, Attribute attr);
  }

  /**
   * Generic logic for formatting a target BUILD-style.
   *
   * <p>This logic is implementation-agnostic. So it can be shared across query, cquery, and other
   * implementations.
   */
  public static class TargetOutputter {
    private final Writer writer;
    private final BiPredicate<Rule, Attribute> preserveSelect;
    private final String lineTerm;
    private final Set<Label> printed = CompactHashSet.create();

    /**
     * @param writer where to write output
     * @param preserveSelect a predicate that determines if the given attribute on the given rule is
     *     a <code>select</code> that should be output as-is (without figuring out which branch it
     *     takes). This is useful for implementations that can't evaluate <code>select</code>.
     * @param lineTerm character to add to the end of each line
     */
    public TargetOutputter(
        Writer writer, BiPredicate<Rule, Attribute> preserveSelect, String lineTerm) {
      this.writer = writer;
      this.preserveSelect = preserveSelect;
      this.lineTerm = lineTerm;
    }

    /** Outputs a given target in BUILD-style syntax. */
    public void output(Target target, AttributeReader attrReader) throws IOException {
      Rule rule = target.getAssociatedRule();
      if (rule == null || printed.contains(rule.getLabel())) {
        return;
      }
      outputRule(rule, attrReader, writer);
      printed.add(rule.getLabel());
    }

    /** Outputs a given rule in BUILD-style syntax. */
    private void outputRule(Rule rule, AttributeReader attrReader, Writer writer)
        throws IOException {
      // TODO(b/151151653): display the filenames in root-relative form.
      // This is an incompatible change, but Blaze users (and their editors)
      // must already be equipped to handle relative paths as all compiler
      // error messages are execroot-relative.

      writer.append("# ").append(rule.getLocation().toString()).append(lineTerm);
      writer.append(rule.getRuleClass()).append("(").append(lineTerm);
      writer.append("  name = \"").append(rule.getName()).append("\",").append(lineTerm);

      for (Attribute attr : rule.getAttributes()) {
        // Ignore the "name" attribute here, as we already print it above.
        // This is not strictly necessary, but convention has it that the
        // name attribute is printed first.
        if ("name".equals(attr.getName())) {
          continue;
        }
        if (preserveSelect.test(rule, attr)) {
          writer
              .append("  ")
              .append(attr.getPublicName())
              .append(" = ")
              .append(reconstructSelect(rule, attr))
              .append(",")
              .append(lineTerm);
          continue;
        }
        AttributeValueSource attributeValueSource =
            AttributeValueSource.forRuleAndAttribute(rule, attr);
        if (attributeValueSource != AttributeValueSource.RULE) {
          continue; // Don't print default values.
        }

        Iterable<Object> values = attrReader.getPossibleValues(rule, attr);
        if (Iterables.size(values) != 1) {
          // Computed defaults that depend on configurable attributes can have multiple values.
          continue;
        }
        writer
            .append("  ")
            .append(attr.getPublicName())
            .append(" = ")
            .append(outputRawAttrValue(Iterables.getOnlyElement(values)))
            .append(",")
            .append(lineTerm);
      }
      writer.append(")").append(lineTerm);

      // Display the instantiation stack, if any.
      appendStack(
          String.format("# Rule %s instantiated at (most recent call last):", rule.getName()),
          rule.getCallStack().toList());

      // Display the stack of the rule class definition, if any.
      appendStack(
          String.format("# Rule %s defined at (most recent call last):", rule.getRuleClass()),
          rule.getRuleClassObject().getCallStack());

      // TODO(adonovan): also list inputs and outputs of the rule.

      writer.append(lineTerm);
    }

    private void appendStack(String title, List<StarlarkThread.CallStackEntry> stack)
        throws IOException {
      // For readability, ensure columns line up.
      int maxLocLen = 0;
      for (StarlarkThread.CallStackEntry fr : stack) {
        maxLocLen = Math.max(maxLocLen, fr.location.toString().length());
      }
      if (maxLocLen > 0) {
        writer.append(title).append(lineTerm);
        for (StarlarkThread.CallStackEntry fr : stack) {
          String loc = fr.location.toString(); // TODO(b/151151653): display root-relative
          // Java's String.format doesn't support
          // right-padding with %*s, so we must loop.
          writer.append("#   ").append(loc);
          for (int i = loc.length(); i < maxLocLen; i++) {
            writer.append(' ');
          }
          writer.append(" in ").append(fr.name).append(lineTerm);
        }
      }
    }

    /** Outputs the given attribute value BUILD-style. Does not support selects. */
    private String outputRawAttrValue(Object value) {
      if (value instanceof License) {
        List<String> licenseTypes = new ArrayList<>();
        for (License.LicenseType licenseType : ((License) value).getLicenseTypes()) {
          licenseTypes.add(Ascii.toLowerCase(licenseType.toString()));
        }
        value = licenseTypes;
      } else if (value instanceof TriState) {
        value = ((TriState) value).toInt();
      }
      return new Printer() {
        // Print labels in their canonical form.
        @Override
        public Printer repr(Object o) {
          return super.repr(o instanceof Label ? ((Label) o).getCanonicalForm() : o);
        }
      }.repr(value).toString();
    }

    /**
     * Outputs a <code>select</code> BUILD-style without trying to resolve which branch it takes.
     */
    private String reconstructSelect(Rule rule, Attribute attr) {
      List<String> selectors = new ArrayList<>();
      RawAttributeMapper attributeMap = RawAttributeMapper.of(rule);
      for (BuildType.Selector<?> selector :
          ((BuildType.SelectorList<?>) attributeMap.getRawAttributeValue(rule, attr))
              .getSelectors()) {
        if (selector.isUnconditional()) {
          selectors.add(
              outputRawAttrValue(
                  Iterables.getOnlyElement(selector.getEntries().entrySet()).getValue()));
        } else {
          selectors.add(String.format("select(%s)", outputRawAttrValue(selector.getEntries())));
        }
      }
      return String.join(" + ", selectors);
    }
  }

  /** Query's implementation. */
  @Override
  public OutputFormatterCallback<Target> createPostFactoStreamCallback(
      OutputStream out, final QueryOptions options) {
    return new BuildOutputFormatterCallback(out, options.getLineTerminator());
  }

  @Override
  public ThreadSafeOutputFormatterCallback<Target> createStreamCallback(
      OutputStream out, QueryOptions options, QueryEnvironment<?> env) {
    return new SynchronizedDelegatingOutputFormatterCallback<>(
        createPostFactoStreamCallback(out, options));
  }

  private static class BuildOutputFormatterCallback extends TextOutputFormatterCallback<Target> {
    private final TargetOutputter targetOutputter;

    BuildOutputFormatterCallback(OutputStream out, String lineTerm) {
      super(out);
      this.targetOutputter =
          new TargetOutputter(
              writer,
              (rule, attr) -> RawAttributeMapper.of(rule).isConfigurable(attr.getName()),
              lineTerm);
    }

    @Override
    public void processOutput(Iterable<Target> partialResult) throws IOException {
      for (Target target : partialResult) {
        targetOutputter.output(
            target,
            // Multiple possible values are ignored by the outputter.
            (rule, attr) ->
                PossibleAttributeValues.forRuleAndAttribute(
                    rule, attr, /*mayTreatMultipleAsNone=*/ true));
      }
    }
  }

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