// 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.analysis.config;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * A helper class to compute and inject a defaults package into the package cache.
 *
 * <p>The <code>//tools/defaults</code> package provides a mechanism let tool locations be specified
 * over the commandline, without requiring any special support in the rule code. As such, it can be
 * used in genrule <code>$(location)</code> substitutions.
 *
 * <p>It works as follows:
 *
 * <ul>
 *   <li>SomeLanguage.createCompileAction will refer to a host-configured target for the compiler by
 *       looking for <code>env.getHostPrerequisiteArtifact("$somelanguage_compiler")</code>.
 *   <li>the attribute <code>$somelanguage_compiler</code> is defined in the {@link RuleDefinition}
 *       subclass for that language.
 *   <li>if the attribute cannot be set on the command-line, its value may be a normal label.
 *   <li>if the attribute can be set on the command-line, its value will be <code>
 *       //tools/defaults:somelanguage_compiler</code>.
 *   <li>in the latter case, the {@link BuildConfiguration.Fragment} subclass will define the option
 *       (with an existing target, eg. <code>//third_party/somelanguage:compiler</code>), and return
 *       the name in its implementation of {@link FragmentOptions#getDefaultsLabels}.
 *   <li>On startup, the rule is wired up with <code>//tools/defaults:somelanguage_compiler</code>.
 *   <li>On starting a build, the <code>//tools/defaults</code> package is synthesized, using the
 *       values as specified on the command-line. The contents of <code>tools/defaults/BUILD</code>
 *       is ignored.
 *   <li>Hence, changes in the command line values for tools are now handled exactly as if they were
 *       changes in a BUILD file.
 *   <li>The file <code>tools/defaults/BUILD</code> must exist, so we create a package in that
 *       location.
 *   <li>The code in {@link DefaultsPackage} can dump the synthesized package as a BUILD file, so
 *       external tooling does not need to understand the intricacies of handling command-line
 *       options.
 * </ul>
 *
 * <p>For built-in rules (as opposed to genrules), late-bound labels provide an alternative method
 * of depending on command-line values. These work by declaring attribute default values to be
 * {@link LateBoundDefault} instances, whose <code>resolve(Rule rule, AttributeMap attributes,
 * FragmentT configuration)</code> method will have access to a {@link BuildConfiguration.Fragment},
 * which in turn may depend on command line flag values.
 */
public final class DefaultsPackage {

  // The template contents are broken into lines such that the resulting file has no more than 80
  // characters per line.
  private static final String HEADER = ""
      + "# DO NOT EDIT THIS FILE!\n"
      + "#\n"
      + "# Bazel does not read this file. Instead, it internally replaces the targets in\n"
      + "# this package with the correct packages as given on the command line.\n"
      + "#\n"
      + "# If these options are not given on the command line, Bazel will use the exact\n"
      + "# same targets as given here."
      + "\n"
      + "package(default_visibility = ['//visibility:public'])\n";

  /**
   * The map from entries to their values.
   */
  private ImmutableMap<String, ImmutableSet<Label>> values;

  private DefaultsPackage(BuildOptions buildOptions) {
    values = buildOptions.getDefaultsLabels();
  }

  private String labelsToString(Set<Label> labels) {
    StringBuilder result = new StringBuilder();
    for (Label label : labels) {
      if (result.length() != 0) {
        result.append(", ");
      }
      result.append("'").append(label).append("'");
    }
    return result.toString();
  }

  /**
   * Returns a string of the defaults package with the given settings.
   */
  private String getContent() {
    Preconditions.checkState(!values.isEmpty());
    StringBuilder result = new StringBuilder(HEADER);
    for (Map.Entry<String, ImmutableSet<Label>> entry : values.entrySet()) {
      result
          .append("filegroup(name = '")
          .append(entry.getKey().toLowerCase(Locale.US)).append("',\n")
          .append("          srcs = [")
          .append(labelsToString(entry.getValue())).append("])\n");
    }

    return result.toString();
  }

  /**
   * Returns the defaults package for the default settings.
   */
  public static String getDefaultsPackageContent(
      Iterable<Class<? extends FragmentOptions>> options, InvocationPolicy invocationPolicy) {
    return getDefaultsPackageContent(BuildOptions.createDefaults(options, invocationPolicy));
  }

  /**
   * Returns the defaults package for the given options.
   */
  public static String getDefaultsPackageContent(BuildOptions buildOptions) {
    return new DefaultsPackage(buildOptions).getContent();
  }

  public static void parseAndAdd(Set<Label> labels, String optionalLabel) {
    if (optionalLabel != null) {
      Label label = parseOptionalLabel(optionalLabel);
      if (label != null) {
        labels.add(label);
      }
    }
  }

  public static Label parseOptionalLabel(String value) {
    try {
      return Label.parseAbsolute(value, ImmutableMap.of());
    } catch (LabelSyntaxException e) {
      // We ignore this exception here - it will cause an error message at a later time.
      return null;
    }
  }
}
