// 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.EvalUtils;
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 List<?> && EvalUtils.isImmutable(value)) {
        // Display it as a list (and not as a tuple). Attributes can never be tuples.
        value = new ArrayList<>((List<?>) value);
      } 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;
    }
  }
}
