// 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 {
    PossibleAttributeValues 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;
        }
        PossibleAttributeValues values = attrReader.getPossibleValues(rule, attr);
        if (values.getSource() != AttributeValueSource.RULE) {
          continue; // Don't print default values.
        }
        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, (rule, attr) -> PossibleAttributeValues.forRuleAndAttribute(rule, attr));
      }
    }
  }

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