// 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.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.analysis.configuredtargets.RuleConfiguredTarget;
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;
import java.util.logging.Logger;

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

  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,
            RuleConfiguredTarget.Mode.TARGET,
            XcodeVersionRuleData.class);

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

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

    AvailableXcodesInfo localVersions =
        ruleContext.getPrerequisite(
            XcodeConfigRule.LOCAL_VERSIONS_ATTR_NAME,
            RuleConfiguredTarget.Mode.TARGET,
            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.info(
        String.format("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);

    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.info(
        String.format(
            "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.info(
        String.format(
            "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) {
        return Maps.immutableEntry(specifiedVersionFromRemote, Availability.BOTH);
      } 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())));
      }
    }
    if (preferMutualXcode && !mutuallyAvailableVersions.isEmpty()) {
      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);
    }
    // Select the local default.
    Availability availability = null;
    XcodeVersionRuleData localVersion = null;
    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())) {
      availability = Availability.BOTH;
      localVersion =
          remoteAliasesToVersionMap.get(localVersions.getDefaultVersion().getVersion().toString());
    } else {
      for (String versionNumber : localVersions.getDefaultVersion().getAliases()) {
        if (remoteAliasesToVersionMap.containsKey(versionNumber)) {
          availability = Availability.BOTH;
          localVersion = remoteAliasesToVersionMap.get(versionNumber);
          break;
        }
      }
      if (localVersion == null) {
        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.");
        availability = Availability.LOCAL;
        localVersion = localVersions.getDefaultVersion();
      }
    }
    return Maps.immutableEntry(localVersion, availability);
  }

  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,
        RuleConfiguredTarget.Mode.TARGET,
        com.google.devtools.build.lib.rules.apple.XcodeConfigInfo.PROVIDER);
  }
}
