// 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.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;
import javax.annotation.Nullable;

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

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

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

  @Override
  @Nullable
  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);

    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);
    }
    // A version is mutually available (available both locally and remotely) if the local version
    // attribute matches either the version attribute or one of the aliases of the remote version.
    // mutuallyAvailableVersions is a subset of available versions in remoteVersions.
    // We assume the "version" attribute in local xcode_version contains a full version string,
    // e.g. including the build, while the versions in "alias" attribute may be less granular.
    // On the other hand, it's could be either way for remote xcode_version.
    Set<XcodeVersionRuleData> mutuallyAvailableVersions = Sets.newHashSet();
    if (localVersions.getAvailableVersions() != null) {
      for (XcodeVersionRuleData local : localVersions.getAvailableVersions()) {
        if (remoteAliasesToVersionMap.containsKey(local.getVersion().toString())) {
          mutuallyAvailableVersions.add(
              remoteAliasesToVersionMap.get(local.getVersion().toString()));
        }
      }
    }
    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);
  }
}
