// 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 com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.StarlarkThread;
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;

/**
 * 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 LabelPrinter().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";
  }

  /** Prints labels in their canonical form. */
  private static class LabelPrinter extends Printer.BasePrinter {
    @Override
    public LabelPrinter repr(Object o) {
      if (o instanceof Label) {
        writeString(((Label) o).getCanonicalForm());
      } else {
        super.repr(o);
      }
      return this;
    }
  }
}
