// Copyright 2017 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.rules.config;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment;
import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import java.util.Map;
import java.util.Optional;
import java.util.SortedMap;
import javax.annotation.Nullable;

/**
 * Configuration fragment for Android's config_feature_flag, flags which can be defined in BUILD
 * files.
 */
@AutoCodec
public final class ConfigFeatureFlagConfiguration extends BuildConfiguration.Fragment {
  /**
   * A configuration fragment loader able to create instances of {@link
   * ConfigFeatureFlagConfiguration} from {@link ConfigFeatureFlagOptions}.
   */
  public static final class Loader implements ConfigurationFragmentFactory {
    @Override
    public BuildConfiguration.Fragment create(
        ConfigurationEnvironment env, BuildOptions buildOptions)
        throws InvalidConfigurationException {
      ConfigFeatureFlagOptions options = buildOptions.get(ConfigFeatureFlagOptions.class);
      if (!options.unknownFlags.isEmpty()) {
        ImmutableList.Builder<String> errorMessage = new ImmutableList.Builder<>();
        for (Label missingLabel : options.unknownFlags) {
          errorMessage.add(
              String.format(
                  "Feature flag %1$s was accessed in a configuration it is not present in. All "
                      + "targets which depend on %1$s directly or indirectly must name it in their "
                      + "transitive_configs attribute.",
                  missingLabel));
        }
        throw new InvalidConfigurationException(
            "Some feature flags were incorrectly specified:\n"
                + Joiner.on("\n").join(errorMessage.build()));
      }

      return new ConfigFeatureFlagConfiguration(options);
    }

    @Override
    public Class<? extends BuildConfiguration.Fragment> creates() {
      return ConfigFeatureFlagConfiguration.class;
    }

    @Override
    public ImmutableSet<Class<? extends FragmentOptions>> requiredOptions() {
      return ImmutableSet.<Class<? extends FragmentOptions>>of(ConfigFeatureFlagOptions.class);
    }
  }

  /** Exception thrown when a flag is accessed in a configuration it is not present in. */
  public static final class MissingFlagException extends RuntimeException {
    public MissingFlagException(Label label) {
      super(
          String.format(
              "Feature flag %1$s was accessed in a configuration it was trimmed from.", label));
    }
  }

  private final ImmutableSortedMap<Label, String> flagValues;
  private final ImmutableSortedSet<Label> knownDefaultFlags;
  private final boolean isTrimmed;
  @Nullable private final String flagHash;

  /** Creates a new configuration fragment from the given {@link ConfigFeatureFlagOptions}. */
  public ConfigFeatureFlagConfiguration(ConfigFeatureFlagOptions options) {
    // TODO(mstaib): we'd love to only construct these when we're trimmed, but this is still what
    // the top level looks like - make constructing an untrimmed configuration an error when no
    // configurations are constructed untrimmed.
    this(
        options.getFlagValues(),
        options.getKnownDefaultFlags().orElse(ImmutableSortedSet.of()),
        options.enforceTransitiveConfigsForConfigFeatureFlag && options.isTrimmed());
  }

  @AutoCodec.Instantiator
  ConfigFeatureFlagConfiguration(
      ImmutableSortedMap<Label, String> flagValues,
      ImmutableSortedSet<Label> knownDefaultFlags,
      boolean isTrimmed) {
    this.flagValues = flagValues;
    this.knownDefaultFlags = knownDefaultFlags;
    this.isTrimmed = isTrimmed;
    // We don't hash flags set to their default values; all valid configurations of a target have
    // the same set of known flags, so the set of flags set to something other than their default
    // values is enough to disambiguate configurations. Similarly, isTrimmed need not be hashed;
    // enforceTransitiveConfigsForConfigFeatureFlag should not change within a build, and when it's
    // enabled, the only configuration which is untrimmed (the top-level configuration) shouldn't
    // be used for any actual targets.
    this.flagHash = flagValues.isEmpty() ? null : hashFlags(flagValues);
  }

  /** Converts the given flag values into a string hash for use as an output directory fragment. */
  private static String hashFlags(SortedMap<Label, String> flagValues) {
    // This hash function is relatively fast and stable between JVM invocations.
    Hasher hasher = Hashing.murmur3_128().newHasher();

    for (Map.Entry<Label, String> flag : flagValues.entrySet()) {
      hasher.putUnencodedChars(flag.getKey().toString());
      hasher.putByte((byte) 0);
      hasher.putUnencodedChars(flag.getValue());
      hasher.putByte((byte) 0);
    }
    return hasher.hash().toString();
  }

  /**
   * Retrieves the value of a configuration flag.
   *
   * <p>If the flag is not set in the current configuration, then the returned value will be absent.
   *
   * <p>If the flag has been trimmed from the current configuration, a RuntimeException
   * (MissingFlagException) will be thrown. Because the configuration should fail to construct if a
   * required flag is missing, and because config_feature_flag (the only intended user of this
   * method) automatically requires itself, this should not come to pass.
   *
   * <p>This method should only be used by the rule whose label is passed here. Other rules should
   * depend on that rule and read a provider exported by it. To encourage callers of this method to
   * do the right thing, this class takes {@link ArtifactOwner} instead of {@link Label}; to get the
   * ArtifactOwner for a rule, call {@code ruleContext.getOwner()}.
   */
  public Optional<String> getFeatureFlagValue(ArtifactOwner owner) {
    if (flagValues.containsKey(owner.getLabel())) {
      return Optional.of(flagValues.get(owner.getLabel()));
    } else if (!isTrimmed || knownDefaultFlags.contains(owner.getLabel())) {
      return Optional.empty();
    } else {
      throw new MissingFlagException(owner.getLabel());
    }
  }

  /**
   * Returns a fragment of the output directory name for this configuration, based on the set of
   * flags and their values. It will be {@code null} if no flags are set.
   */
  @Nullable
  @Override
  public String getOutputDirectoryName() {
    return flagHash;
  }
}
