// 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 com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
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.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions.AppleBitcodeMode;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.util.Preconditions;

import java.util.Map;

import javax.annotation.Nullable;

/**
 * A configuration containing flags required for Apple platforms and tools.
 */
@SkylarkModule(name = "apple", doc = "A configuration fragment for Apple platforms")
@Immutable
public class AppleConfiguration extends BuildConfiguration.Fragment {
  public static final String XCODE_VERSION_ENV_NAME = "XCODE_VERSION_OVERRIDE";
  /**
   * Environment variable name for the apple SDK version. If unset, uses the system default of the
   * host for the platform in the value of {@link #APPLE_SDK_PLATFORM_ENV_NAME}.
   **/
  public static final String APPLE_SDK_VERSION_ENV_NAME = "APPLE_SDK_VERSION_OVERRIDE";
  /**
   * Environment variable name for the apple SDK platform. This should be set for all actions that
   * require an apple SDK. The valid values consist of {@link Platform} names.
   **/
  public static final String APPLE_SDK_PLATFORM_ENV_NAME = "APPLE_SDK_PLATFORM";

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

  private final DottedVersion iosSdkVersion;
  private final DottedVersion watchOsSdkVersion;
  private final DottedVersion tvOsSdkVersion;
  private final DottedVersion macOsXSdkVersion;
  private final String iosCpu;
  private final Optional<DottedVersion> xcodeVersion;
  private final ImmutableList<String> iosMultiCpus;
  private final AppleBitcodeMode bitcodeMode;
  private final Label xcodeConfigLabel;
  @Nullable private final Label defaultProvisioningProfileLabel;

  AppleConfiguration(AppleCommandLineOptions appleOptions,
      Optional<DottedVersion> xcodeVersionOverride,
      DottedVersion iosSdkVersion) {
    this.iosSdkVersion = Preconditions.checkNotNull(iosSdkVersion, "iosSdkVersion");
    this.watchOsSdkVersion =
        Preconditions.checkNotNull(appleOptions.watchOsSdkVersion, "watchOsSdkVersion");
    this.tvOsSdkVersion =
        Preconditions.checkNotNull(appleOptions.tvOsSdkVersion, "tvOsSdkVersion");
    this.macOsXSdkVersion =
        Preconditions.checkNotNull(appleOptions.macOsXSdkVersion, "macOsXSdkVersion");

    this.xcodeVersion = Preconditions.checkNotNull(xcodeVersionOverride);
    this.iosCpu = Preconditions.checkNotNull(appleOptions.iosCpu, "iosCpu");
    this.iosMultiCpus = ImmutableList.copyOf(
        Preconditions.checkNotNull(appleOptions.iosMultiCpus, "iosMultiCpus"));
    this.bitcodeMode = appleOptions.appleBitcodeMode;
    this.xcodeConfigLabel =
        Preconditions.checkNotNull(appleOptions.xcodeVersionConfig, "xcodeConfigLabel");
    this.defaultProvisioningProfileLabel = appleOptions.defaultProvisioningProfile;
  }

  /**
   * Returns the SDK version for ios SDKs (whether they be for simulator or device). This is
   * directly derived from --ios_sdk_version.
   *
   * @deprecated - use {@link #getSdkVersionForPlatform()}
   */
  @Deprecated public DottedVersion getIosSdkVersion() {
    return getSdkVersionForPlatform(Platform.IOS_DEVICE);
  }

  /**
   * Returns the SDK version for a platform (whether they be for simulator or device). This is
   * directly derived from command line args.
   */
  public DottedVersion getSdkVersionForPlatform(Platform platform) {
    switch (platform) {
      case IOS_DEVICE:
      case IOS_SIMULATOR:
        return iosSdkVersion;
      case TVOS_DEVICE:
      case TVOS_SIMULATOR:
        return tvOsSdkVersion;
      case WATCHOS_DEVICE:
      case WATCHOS_SIMULATOR:
        return watchOsSdkVersion;
      case MACOS_X:
        return macOsXSdkVersion;
    }
    throw new AssertionError();

  }

  /**
   * Returns the value of the xcode version, if available. This is determined based on a combination
   * of the {@code --xcode_version} build flag and the {@code xcode_config} target defined in the
   * {@code --xcode_version_config} flag.
   */
  public Optional<DottedVersion> getXcodeVersion() {
    return xcodeVersion;
  }

  /**
   * Returns a map of environment variables (derived from configuration) that should be propagated
   * for actions pertaining to building ios applications. Keys are variable names and values are
   * their corresponding values.
   */
  // TODO(bazel-team): Repurpose for non-ios platforms.
  public Map<String, String> getEnvironmentForIosAction() {
    ImmutableMap.Builder<String, String> mapBuilder = ImmutableMap.builder();
    mapBuilder.putAll(appleTargetPlatformEnv(Platform.forIosArch(getIosCpu())));
    return mapBuilder.build();
  }
  
  /**
   * Returns a map of environment variables that should be propagated for actions that build on an
   * apple host system. These environment variables are needed by the apple toolchain. Keys are
   * variable names and values are their corresponding values.
   */
  @SkylarkCallable(
      name = "apple_host_system_env",
      doc =
          "Returns a map of environment variables that should be propagated for actions that "
          + "build on an apple host system. These environment variables are needed by the apple "
          + "toolchain. Keys are variable names and values are their corresponding values."
    )
  public Map<String, String> getAppleHostSystemEnv() {
    Optional<DottedVersion> xcodeVersion = getXcodeVersion();
    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
    if (xcodeVersion.isPresent()) {
      builder.put(AppleConfiguration.XCODE_VERSION_ENV_NAME, xcodeVersion.get().toString());
    }
    return builder.build();   
  }

  /**
   * Returns a map of environment variables (derived from configuration) that should be propagated
   * for actions pertaining to building applications for apple platforms. These environment
   * variables are needed to use apple toolkits. Keys are variable names and values are their
   * corresponding values.
   */
  public Map<String, String> appleTargetPlatformEnv(Platform platform) {
    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();

    // TODO(bazel-team): Handle non-ios platforms.
    if (platform == Platform.IOS_DEVICE || platform == Platform.IOS_SIMULATOR) {
      String sdkVersion = getSdkVersionForPlatform(platform).toString();
      builder.put(AppleConfiguration.APPLE_SDK_VERSION_ENV_NAME, sdkVersion)
          .put(AppleConfiguration.APPLE_SDK_PLATFORM_ENV_NAME, platform.getNameInPlist());
    }
    return builder.build();
  }

  public String getIosCpu() {
    return iosCpu;
  }
  
  /**
   * Returns the platform of the configuration for the current bundle, based on configured
   * architectures (for example, {@code i386} maps to {@link Platform#IOS_SIMULATOR}).
   *
   * <p>If {@link #getIosMultiCpus()} is set, returns {@link Platform#IOS_DEVICE} if any of the
   * architectures matches it, otherwise returns the mapping for {@link #getIosCpu()}.
   *
   * <p>Note that this method should not be used to determine the platform for code compilation.
   * Derive the platform from {@link #getIosCpu()} instead.
   */
  // TODO(bazel-team): This method should be enabled to return multiple values once all call sites
  // (in particular actool, bundlemerge, momc) have been upgraded to support multiple values.
  public Platform getBundlingPlatform() {
    for (String architecture : getIosMultiCpus()) {
      if (Platform.forIosArch(architecture) == Platform.IOS_DEVICE) {
        return Platform.IOS_DEVICE;
      }
    }
    return Platform.forIosArch(getIosCpu());
  }
  
  /**
   * Returns the architecture for which we keep dependencies that should be present only once (in a
   * single architecture).
   *
   * <p>When building with multiple architectures there are some dependencies we want to avoid
   * duplicating: they would show up more than once in the same location in the final application
   * bundle which is illegal. Instead we pick one architecture for which to keep all dependencies
   * and discard any others.
   */
  public String getDependencySingleArchitecture() {
    if (!getIosMultiCpus().isEmpty()) {
      return getIosMultiCpus().get(0);
    }
    return getIosCpu();
  }
  
  /**
   * List of all CPUs that this invocation is being built for. Different from {@link #getIosCpu()}
   * which is the specific CPU <b>this target</b> is being built for.
   */
  public ImmutableList<String> getIosMultiCpus() {
    return iosMultiCpus;
  }

  /**
   * Returns the label of the default provisioning profile to use when bundling/signing an ios
   * application. Returns null if the target platform is not an iOS device (for example, if
   * iOS simulator is being targeted).
   */
  @Nullable public Label getDefaultProvisioningProfileLabel() {
    return defaultProvisioningProfileLabel;
  }
  
  /**
   * Returns the bitcode mode to use for compilation steps. Users can control bitcode
   * mode using the {@code apple_bitcode} build flag.
   * 
   * @see AppleBitcodeMode
   */
  public AppleBitcodeMode getBitcodeMode() {
    return bitcodeMode;
  }

  /**
   * Returns the label of the xcode_config rule to use for resolving the host system xcode version.
   */
  public Label getXcodeConfigLabel() {
    return xcodeConfigLabel;
  }

  /**
   * Loads {@link AppleConfiguration} from build options.
   */
  public static class Loader implements ConfigurationFragmentFactory {
    @Override
    public AppleConfiguration create(ConfigurationEnvironment env, BuildOptions buildOptions)
        throws InvalidConfigurationException {
      AppleCommandLineOptions appleOptions = buildOptions.get(AppleCommandLineOptions.class);
      XcodeVersionProperties xcodeVersionProperties = getXcodeVersionProperties(env, appleOptions);

      DottedVersion iosSdkVersion = (appleOptions.iosSdkVersion != null)
          ? appleOptions.iosSdkVersion : xcodeVersionProperties.getDefaultIosSdkVersion();
      AppleConfiguration configuration =
          new AppleConfiguration(appleOptions, xcodeVersionProperties.getXcodeVersion(),
              iosSdkVersion);

      validate(configuration);
      return configuration;
    }

    private void validate(AppleConfiguration config)
        throws InvalidConfigurationException {
      Optional<DottedVersion> xcodeVersion = config.getXcodeVersion();
      if (config.getBitcodeMode() != AppleBitcodeMode.NONE
          && xcodeVersion.isPresent()
          && xcodeVersion.get().compareTo(MINIMUM_BITCODE_XCODE_VERSION) < 0) {
        throw new InvalidConfigurationException(
            String.format("apple_bitcode mode '%s' is unsupported for xcode version '%s'",
                config.getBitcodeMode(), xcodeVersion.get()));
      }
    }

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

    @Override
    public ImmutableSet<Class<? extends FragmentOptions>> requiredOptions() {
      return ImmutableSet.<Class<? extends FragmentOptions>>of(AppleCommandLineOptions.class);
    }
    
    /**
     * Uses the {@link AppleCommandLineOptions#xcodeVersion} and
     * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and
     * return the effective xcode version properties. Returns absent if no explicit xcode version
     * is declared, and host system defaults should be used.
     *
     * @param env the current configuration environment
     * @param appleOptions the command line options
     * @throws InvalidConfigurationException if the options given (or configuration targets) were
     *     malformed and thus the xcode version could not be determined
     */
    private XcodeVersionProperties getXcodeVersionProperties(ConfigurationEnvironment env,
        AppleCommandLineOptions appleOptions) throws InvalidConfigurationException {
      Optional<DottedVersion> xcodeVersionCommandLineFlag = 
          Optional.fromNullable(appleOptions.xcodeVersion);
      Label xcodeVersionConfigLabel = appleOptions.xcodeVersionConfig;

      return XcodeConfig.resolveXcodeVersion(env, xcodeVersionConfigLabel,
          xcodeVersionCommandLineFlag, "xcode_version_config");
    }
  }
}
