// Copyright 2015 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.apple;

import static com.google.common.base.Preconditions.checkState;
import static java.util.stream.Collectors.joining;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.XcodeConfigEvent;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode;
import com.google.devtools.build.lib.rules.apple.XcodeConfigInfo.Availability;
import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeConfigRuleInfo;
import com.google.devtools.build.lib.xcode.proto.XcodeConfig.XcodeVersionInfo;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Implementation for the {@code xcode_config} rule. */
public class XcodeConfig implements RuleConfiguredTargetFactory {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private static final DottedVersion MINIMUM_BITCODE_XCODE_VERSION =
      DottedVersion.fromStringUnchecked("7");

  /** An exception that signals that an Xcode config setup was invalid. */
  public static class XcodeConfigException extends Exception {

    XcodeConfigException(String reason) {
      super(reason);
    }
  }

  @Override
  public ConfiguredTarget create(RuleContext ruleContext)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    AppleConfiguration appleConfig = ruleContext.getFragment(AppleConfiguration.class);
    AppleCommandLineOptions appleOptions = appleConfig.getOptions();

    XcodeConfigRuleInfo.Builder infoBuilder = XcodeConfigRuleInfo.newBuilder();
    if (appleOptions.xcodeVersion != null) {
      infoBuilder.setXcodeVersionFlag(appleOptions.xcodeVersion);
    }
    XcodeVersionRuleData explicitDefaultVersion =
        ruleContext.getPrerequisite(XcodeConfigRule.DEFAULT_ATTR_NAME, XcodeVersionRuleData.class);

    List<XcodeVersionRuleData> explicitVersions =
        ruleContext.getPrerequisites(
            XcodeConfigRule.VERSIONS_ATTR_NAME, XcodeVersionRuleData.class);

    AvailableXcodesInfo remoteVersions =
        ruleContext.getPrerequisite(
            XcodeConfigRule.REMOTE_VERSIONS_ATTR_NAME,
            AvailableXcodesInfo.PROVIDER);

    AvailableXcodesInfo localVersions =
        ruleContext.getPrerequisite(
            XcodeConfigRule.LOCAL_VERSIONS_ATTR_NAME,
            AvailableXcodesInfo.PROVIDER);

    XcodeVersionProperties xcodeVersionProperties;
    Availability availability = null;
    if (useAvailableXcodesMode(
        explicitVersions, explicitDefaultVersion, localVersions, remoteVersions, ruleContext)) {
      Map.Entry<XcodeVersionRuleData, Availability> xcode =
          resolveXcodeFromLocalAndRemote(
              localVersions,
              remoteVersions,
              ruleContext,
              appleOptions.xcodeVersion,
              appleOptions.preferMutualXcode,
              infoBuilder);
      xcodeVersionProperties = xcode.getKey().getXcodeVersionProperties();
      availability = xcode.getValue();
    } else {
      xcodeVersionProperties =
          resolveExplicitlyDefinedVersion(
              explicitVersions,
              explicitDefaultVersion,
              appleOptions.xcodeVersion,
              ruleContext,
              infoBuilder);
      availability = Availability.UNKNOWN;
    }
    logger.atInfo().log("Using Xcode version %s", xcodeVersionProperties.getXcodeVersionString());
    if (xcodeVersionProperties.getXcodeVersion().isPresent()) {
      infoBuilder
          .setSelectedVersion(xcodeVersionProperties.getXcodeVersionString())
          .setSelectedVersionAvailability(
              XcodeConfigRuleInfo.Availability.valueOf(availability.name()));
    }
    ruleContext
        .getAnalysisEnvironment()
        .getEventHandler()
        .post(new XcodeConfigEvent(infoBuilder.build()));
    DottedVersion iosSdkVersion =
        (appleOptions.iosSdkVersion != null)
            ? DottedVersion.maybeUnwrap(appleOptions.iosSdkVersion)
            : xcodeVersionProperties.getDefaultIosSdkVersion();
    DottedVersion iosMinimumOsVersion =
        (appleOptions.iosMinimumOs != null)
            ? DottedVersion.maybeUnwrap(appleOptions.iosMinimumOs)
            : iosSdkVersion;
    DottedVersion watchosSdkVersion =
        (appleOptions.watchOsSdkVersion != null)
            ? DottedVersion.maybeUnwrap(appleOptions.watchOsSdkVersion)
            : xcodeVersionProperties.getDefaultWatchosSdkVersion();
    DottedVersion watchosMinimumOsVersion =
        (appleOptions.watchosMinimumOs != null)
            ? DottedVersion.maybeUnwrap(appleOptions.watchosMinimumOs)
            : watchosSdkVersion;
    DottedVersion tvosSdkVersion =
        (appleOptions.tvOsSdkVersion != null)
            ? DottedVersion.maybeUnwrap(appleOptions.tvOsSdkVersion)
            : xcodeVersionProperties.getDefaultTvosSdkVersion();
    DottedVersion tvosMinimumOsVersion =
        (appleOptions.tvosMinimumOs != null)
            ? DottedVersion.maybeUnwrap(appleOptions.tvosMinimumOs)
            : tvosSdkVersion;
    DottedVersion macosSdkVersion =
        (appleOptions.macOsSdkVersion != null)
            ? DottedVersion.maybeUnwrap(appleOptions.macOsSdkVersion)
            : xcodeVersionProperties.getDefaultMacosSdkVersion();
    DottedVersion macosMinimumOsVersion =
        (appleOptions.macosMinimumOs != null)
            ? DottedVersion.maybeUnwrap(appleOptions.macosMinimumOs)
            : macosSdkVersion;

    XcodeConfigInfo xcodeVersions =
        new XcodeConfigInfo(
            iosSdkVersion,
            iosMinimumOsVersion,
            watchosSdkVersion,
            watchosMinimumOsVersion,
            tvosSdkVersion,
            tvosMinimumOsVersion,
            macosSdkVersion,
            macosMinimumOsVersion,
            xcodeVersionProperties.getXcodeVersion().orNull(),
            availability,
            appleOptions.xcodeVersion,
            appleOptions.includeXcodeExecutionRequirements);

    AppleBitcodeMode bitcodeMode = appleConfig.getBitcodeMode();
    DottedVersion xcodeVersion = xcodeVersions.getXcodeVersion();
    if (bitcodeMode != AppleBitcodeMode.NONE
        && xcodeVersion != null
        && xcodeVersion.compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) {
      ruleContext.throwWithRuleError(
          String.format(
              "apple_bitcode mode '%s' is unsupported for xcode version '%s'",
              bitcodeMode, xcodeVersion));
    }

    return new RuleConfiguredTargetBuilder(ruleContext)
        .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
        .addNativeDeclaredProvider(xcodeVersions)
        .addNativeDeclaredProvider(xcodeVersionProperties)
        .build();
  }

  /**
   * Returns {@code true} if the xcode version will be determined from {@code local_versions} and
   * {@code remote_versions}.
   *
   * @throws RuleErrorException if attributes from both modes have been set.
   */
  private static boolean useAvailableXcodesMode(
      List<XcodeVersionRuleData> explicitVersions,
      XcodeVersionRuleData explicitDefaultVersion,
      AvailableXcodesInfo localVersions,
      AvailableXcodesInfo remoteVersions,
      RuleContext ruleContext)
      throws RuleErrorException {
    if ((remoteVersions != null && !Iterables.isEmpty(remoteVersions.getAvailableVersions()))) {
      if (!explicitVersions.isEmpty()) {
        ruleContext.ruleError("'versions' may not be set if '[local,remote]_versions' is set.");
      }
      if (explicitDefaultVersion != null) {
        ruleContext.ruleError("'default' may not be set if '[local,remote]_versions' is set.");
      }
      if (localVersions == null || Iterables.isEmpty(localVersions.getAvailableVersions())) {
        ruleContext.throwWithRuleError(
            "if 'remote_versions' are set, you must also set 'local_versions'");
      }
      return true;
    }
    return false;
  }
  /**
   * Returns the {@link XcodeVersionProperties} selected by the {@code--xcode_version} flag from the
   * {@code versions} attribute of the {@code xcode_config} target explicitly defined in the {@code
   * --xcode_version_config} build flag. This is not used if the {@code local_versions} or {@code
   * remote_versions} attributes are set. If {@code --xcode_version} is unspecified, then this will
   * return the default rule data as specified in the {@code --xcode_version_config} target.
   *
   * @throws RuleErrorException if required dependencies are missing or ill formatted.
   */
  private static XcodeVersionProperties resolveExplicitlyDefinedVersion(
      List<XcodeVersionRuleData> explicitVersions,
      XcodeVersionRuleData explicitDefaultVersion,
      String versionOverrideFlag,
      RuleContext ruleContext,
      XcodeConfigRuleInfo.Builder infoBuilder)
      throws RuleErrorException {
    if (explicitDefaultVersion != null
        && !Iterables.any(
            explicitVersions,
            ruleData -> ruleData.getLabel().equals(explicitDefaultVersion.getLabel()))) {
      ruleContext.throwWithRuleError(
          String.format(
              "default label '%s' must be contained in versions attribute",
              explicitDefaultVersion.getLabel()));
    }
    if (explicitVersions.isEmpty()) {
      if (explicitDefaultVersion != null) {
        ruleContext.throwWithRuleError("default label must be contained in versions attribute");
      }
      return XcodeVersionProperties.unknownXcodeVersionProperties();
    }
    if (explicitDefaultVersion == null) {
      ruleContext.throwWithRuleError(
          "if any versions are specified, a default version must be specified");
    }
    logger.atInfo().log(
        "Determining Xcode version using single-location Xcodes mode: versions=[%s]",
        printableXcodeVersions(explicitVersions));
    for (XcodeVersionRuleData version : explicitVersions) {
      infoBuilder.addExplicitVersions(
          XcodeVersionInfo.newBuilder()
              .setVersion(version.getVersion().toString())
              .addAllAliases(version.getAliases())
              .build());
    }
    infoBuilder.setDefaultVersion(explicitDefaultVersion.getVersion().toString());

    Map<String, XcodeVersionRuleData> aliasesToVersionMap = null;
    try {
      aliasesToVersionMap = aliasesToVersionMap(explicitVersions);
    } catch (XcodeConfigException e) {
      throw ruleContext.throwWithRuleError(e);
    }

    if (!Strings.isNullOrEmpty(versionOverrideFlag)) {
      // The version override flag is not necessarily an actual version - it may be a version
      // alias.
      XcodeVersionRuleData explicitVersion = aliasesToVersionMap.get(versionOverrideFlag);
      if (explicitVersion != null) {
        return explicitVersion.getXcodeVersionProperties();
      } else {
        ruleContext.throwWithRuleError(
            String.format(
                "--xcode_version=%1$s specified, but '%1$s' is not an available Xcode version. "
                    + "available versions: [%2$s]. If you believe you have '%1$s' installed, try "
                    + "running \"bazel shutdown\", and then re-run your command.",
                versionOverrideFlag, printableXcodeVersions(explicitVersions)));
      }
    }

    return explicitDefaultVersion.getXcodeVersionProperties();
  }

  /**
   * Returns the {@link XcodeVersionRuleData} and availability associated with the {@code
   * xcode_version} target determined from its {@code remote_xcodes} and {@code local_xcodes}
   * dependencies and selected by the {@code --xcode_version} flag. The version specified by {@code
   * --xcode_version} will be used if it's specified and is available locally or remotely (or both).
   * If {@code --xcode_version} is unspecified, then this will return the newest mutually available
   * version if possibls, otherwise the default local version.
   */
  private static Map.Entry<XcodeVersionRuleData, Availability> resolveXcodeFromLocalAndRemote(
      AvailableXcodesInfo localVersions,
      AvailableXcodesInfo remoteVersions,
      RuleContext ruleContext,
      String versionOverrideFlag,
      boolean preferMutualXcode,
      XcodeConfigRuleInfo.Builder infoBuilder)
      throws RuleErrorException {

    Map<String, XcodeVersionRuleData> localAliasesToVersionMap;
    Map<String, XcodeVersionRuleData> remoteAliasesToVersionMap;
    try {
      localAliasesToVersionMap = aliasesToVersionMap(localVersions.getAvailableVersions());
      remoteAliasesToVersionMap = aliasesToVersionMap(remoteVersions.getAvailableVersions());
    } catch (XcodeConfigException e) {
      throw ruleContext.throwWithRuleError(e);
    }
    // Mutually available Xcode versions are versions that are available both locally and remotely,
    // but are referred to by the aliases listed in remote_xcodes.
    Set<XcodeVersionRuleData> mutuallyAvailableVersions = Sets.newHashSet();
    for (String version : localAliasesToVersionMap.keySet()) {
      if (remoteAliasesToVersionMap.containsKey(version)) {
        mutuallyAvailableVersions.add(remoteAliasesToVersionMap.get(version));
      }
    }
    logger.atInfo().log(
        "Determining Xcode version using available Xcodes mode:"
            + " local=[%s], remote=[%s], mutual=[%s]",
        printableXcodeVersions(localVersions.getAvailableVersions()),
        printableXcodeVersions(remoteVersions.getAvailableVersions()),
        printableXcodeVersions(mutuallyAvailableVersions));

    for (XcodeVersionRuleData version : remoteVersions.getAvailableVersions()) {
      infoBuilder.addRemoteVersions(
          XcodeVersionInfo.newBuilder()
              .setVersion(version.getVersion().toString())
              .addAllAliases(version.getAliases()));
    }
    for (XcodeVersionRuleData version : localVersions.getAvailableVersions()) {
      infoBuilder.addLocalVersions(
          XcodeVersionInfo.newBuilder()
              .setVersion(version.getVersion().toString())
              .addAllAliases(version.getAliases()));
    }
    for (XcodeVersionRuleData version : mutuallyAvailableVersions) {
      infoBuilder.addMutualVersions(
          XcodeVersionInfo.newBuilder()
              .setVersion(version.getVersion().toString())
              .addAllAliases(version.getAliases()));
    }
    infoBuilder.setDefaultVersion(localVersions.getDefaultVersion().getVersion().toString());

    if (!Strings.isNullOrEmpty(versionOverrideFlag)) {
      XcodeVersionRuleData specifiedVersionFromRemote =
          remoteAliasesToVersionMap.get(versionOverrideFlag);
      XcodeVersionRuleData specifiedVersionFromLocal =
          localAliasesToVersionMap.get(versionOverrideFlag);
      if (specifiedVersionFromLocal != null && specifiedVersionFromRemote != null) {
        XcodeVersionRuleData strictlyMatchedRemoteVersion =
            remoteAliasesToVersionMap.get(specifiedVersionFromLocal.getVersion().toString());
        if (strictlyMatchedRemoteVersion != null) {
          return Maps.immutableEntry(specifiedVersionFromRemote, Availability.BOTH);
        } else {
          ruleContext.throwWithRuleError(
              String.format(
                  "Xcode version %1$s was selected, either because --xcode_version was passed, or"
                      + " because xcode-select points to this version locally. This corresponds to"
                      + " local Xcode version %2$s. That build of version %1$s is not available"
                      + " remotely, but there is a different build of version %1$s, which has"
                      + " version %3$s and aliases %4$s. You probably meant to use this version."
                      + " Please download it *and delete version %2$s*, then run `blaze shutdown`"
                      + " to continue using dynamic execution. If you really did intend to use"
                      + " local version %2$s, please either specify it fully with"
                      + " --xcode_version=%2$s or disable dynamic (and thus remote) execution.",
                  versionOverrideFlag,
                  specifiedVersionFromLocal.getVersion(),
                  specifiedVersionFromRemote.getVersion(),
                  specifiedVersionFromRemote.getAliases()));
        }
      } else if (specifiedVersionFromLocal != null) {
        String error =
            String.format(
                "--xcode_version=%1$s specified, but it is not available remotely. Actions"
                    + " requiring Xcode will be run locally, which could make your build"
                    + " slower.",
                versionOverrideFlag);
        if (!mutuallyAvailableVersions.isEmpty()) {
          error =
              error
                  + String.format(
                      " Consider using one of [%s].",
                      printableXcodeVersions(mutuallyAvailableVersions));
        }
        ruleContext.ruleWarning(error);
        return Maps.immutableEntry(specifiedVersionFromLocal, Availability.LOCAL);
      } else if (specifiedVersionFromRemote != null) {
        ruleContext.ruleWarning(
            String.format(
                "--xcode_version=%1$s specified, but it is not available locally. Your build"
                    + " will fail if any actions require a local Xcode. If you believe you have"
                    + " '%1$s' installed, try running \"blaze shutdown\", and then re-run your"
                    + " command.  localy available versions: [%2$s]. remotely available"
                    + " versions: [%3$s]",
                versionOverrideFlag,
                printableXcodeVersions(localVersions.getAvailableVersions()),
                printableXcodeVersions(remoteVersions.getAvailableVersions())));
        return Maps.immutableEntry(specifiedVersionFromRemote, Availability.REMOTE);
      } else { // if (specifiedVersionFromRemote == null && specifiedVersionFromLocal == null)
        ruleContext.throwWithRuleError(
            String.format(
                "--xcode_version=%1$s specified, but '%1$s' is not an available Xcode version."
                    + " localy available versions: [%2$s]. remotely available versions:"
                    + " [%3$s]. If you believe you have '%1$s' installed, try running \"blaze"
                    + " shutdown\", and then re-run your command.",
                versionOverrideFlag,
                printableXcodeVersions(localVersions.getAvailableVersions()),
                printableXcodeVersions(remoteVersions.getAvailableVersions())));
      }
    }
    Availability availability = null;
    XcodeVersionRuleData localVersion = null;
    // If there aren't any mutually available versions, select the local default.
    if (mutuallyAvailableVersions.isEmpty()) {
      ruleContext.ruleWarning(
          String.format(
              "Using a local Xcode version, '%s', since there are no"
                  + " remotely available Xcodes on this machine. Consider downloading one of the"
                  + " remotely available Xcode versions (%s) in order to get the best build"
                  + " performance.",
              localVersions.getDefaultVersion().getVersion(),
              printableXcodeVersions(remoteVersions.getAvailableVersions())));
      localVersion = localVersions.getDefaultVersion();
      availability = Availability.LOCAL;
    } else if (remoteAliasesToVersionMap.containsKey(
        localVersions
            .getDefaultVersion()
            .getVersion()
            .toString())) { // If the local default version is also available remotely, use it.
      availability = Availability.BOTH;
      localVersion =
          remoteAliasesToVersionMap.get(localVersions.getDefaultVersion().getVersion().toString());
    } else { // If an alias of the local default version is available remotely, use it.
      for (String versionNumber : localVersions.getDefaultVersion().getAliases()) {
        if (remoteAliasesToVersionMap.containsKey(versionNumber)) {
          availability = Availability.BOTH;
          localVersion = remoteAliasesToVersionMap.get(versionNumber);
          break;
        }
      }
    }
    if (localVersion != null) {
      return Maps.immutableEntry(localVersion, availability);
    }
    // The local default is not available remotely.
    if (preferMutualXcode) { // If we prefer a mutually available version, the newest one.
      DottedVersion newestVersionNumber = DottedVersion.fromStringUnchecked("0.0");
      XcodeVersionRuleData defaultVersion = null;
      for (XcodeVersionRuleData versionRuleData : mutuallyAvailableVersions) {
        if (versionRuleData.getVersion().compareTo(newestVersionNumber) > 0) {
          defaultVersion = versionRuleData;
          newestVersionNumber = defaultVersion.getVersion();
        }
      }
      // This should never occur. All input versions should be above 0.0.
      checkState(defaultVersion != null);
      return Maps.immutableEntry(defaultVersion, Availability.BOTH);
    } else { // Use the local default.
        ruleContext.ruleWarning(
            "You passed --experimental_prefer_mutual_xcode=false, which prevents Bazel from"
                + " selecting an Xcode version that optimizes your performance. Please consider"
                + " using --experimental_prefer_mutual_xcode=true.");
      return Maps.immutableEntry(localVersions.getDefaultVersion(), Availability.LOCAL);
    }
  }

  private static String printableXcodeVersions(Iterable<XcodeVersionRuleData> xcodeVersions) {
    return Streams.stream(xcodeVersions)
        .map(versionData -> versionData.getVersion().toString())
        .collect(joining(", "));
  }

  /**
   * Returns a map where keys are "names" of xcode versions as defined by the configuration target,
   * and values are the rule data objects which contain information regarding that xcode version.
   *
   * @throws XcodeConfigException if there are duplicate aliases (if two xcode versions were
   *     registered to the same alias)
   */
  private static Map<String, XcodeVersionRuleData> aliasesToVersionMap(
      Iterable<XcodeVersionRuleData> xcodeVersionRules) throws XcodeConfigException {
    Map<String, XcodeVersionRuleData> aliasesToXcodeRules = Maps.newLinkedHashMap();
    if (xcodeVersionRules == null) {
      return aliasesToXcodeRules;
    }
    for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) {
      for (String alias : xcodeVersionRule.getAliases()) {
        if (aliasesToXcodeRules.put(alias, xcodeVersionRule) != null) {
          configErrorDuplicateAlias(alias, xcodeVersionRules);
        }
      }
      // Only add the version as an alias if it's not included in this xcode_version target's
      // aliases (in which case it would have just been added. This offers some leniency in target
      // definition, as it's silly to error if a version is aliased to its own version.
      if (!xcodeVersionRule.getAliases().contains(xcodeVersionRule.getVersion().toString())) {
        if (aliasesToXcodeRules.put(xcodeVersionRule.getVersion().toString(), xcodeVersionRule)
            != null) {
          configErrorDuplicateAlias(xcodeVersionRule.getVersion().toString(), xcodeVersionRules);
        }
      }
    }
    return aliasesToXcodeRules;
  }

  /**
   * Convenience method for throwing an {@link XcodeConfigException} due to presence of duplicate
   * aliases in an {@code xcode_config} target definition.
   */
  private static void configErrorDuplicateAlias(
      String alias, Iterable<XcodeVersionRuleData> xcodeVersionRules) throws XcodeConfigException {

    ImmutableList.Builder<Label> labelsContainingAlias = ImmutableList.builder();
    for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) {
      if (xcodeVersionRule.getAliases().contains(alias)
          || xcodeVersionRule.getVersion().toString().equals(alias)) {
        labelsContainingAlias.add(xcodeVersionRule.getLabel());
      }
    }

    throw new XcodeConfigException(
        String.format(
            "'%s' is registered to multiple labels (%s) in a single xcode_config rule",
            alias, Joiner.on(", ").join(labelsContainingAlias.build())));
  }

  public static XcodeConfigInfo getXcodeConfigInfo(RuleContext ruleContext) {
    return ruleContext.getPrerequisite(
        XcodeConfigRule.XCODE_CONFIG_ATTR_NAME,
        com.google.devtools.build.lib.rules.apple.XcodeConfigInfo.PROVIDER);
  }
}
