// Copyright 2014 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.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.skylarkbuildapi.apple.AppleToolchainApi;
import java.io.Serializable;

/**
 * Utility class for resolving items for the Apple toolchain (such as common tool flags, and paths).
 */
@Immutable
public class AppleToolchain implements AppleToolchainApi<AppleConfiguration> {

  // These next two strings are shared secrets with the xcrunwrapper.sh to allow
  // expansion of DeveloperDir and SDKRoot and runtime, since they aren't known
  // until compile time on any given build machine.
  private static final String DEVELOPER_DIR = "__BAZEL_XCODE_DEVELOPER_DIR__";
  private static final String SDKROOT_DIR = "__BAZEL_XCODE_SDKROOT__";

  // These two paths are framework paths relative to SDKROOT.
  @VisibleForTesting
  public static final String DEVELOPER_FRAMEWORK_PATH = "/Developer/Library/Frameworks";
  @VisibleForTesting
  public static final String SYSTEM_FRAMEWORK_PATH = "/System/Library/Frameworks";

  // There is a handy reference to many clang warning flags at
  // http://nshipster.com/clang-diagnostics/
  // There is also a useful narrative for many Xcode settings at
  // http://www.xs-labs.com/en/blog/2011/02/04/xcode-build-settings/
  public static final ImmutableMap<String, String> DEFAULT_WARNINGS =
      new ImmutableMap.Builder<String, String>()
          .put("GCC_WARN_64_TO_32_BIT_CONVERSION", "-Wshorten-64-to-32")
          .put("CLANG_WARN_BOOL_CONVERSION", "-Wbool-conversion")
          .put("CLANG_WARN_CONSTANT_CONVERSION", "-Wconstant-conversion")
          // Double-underscores are intentional - thanks Xcode.
          .put("CLANG_WARN__DUPLICATE_METHOD_MATCH", "-Wduplicate-method-match")
          .put("CLANG_WARN_EMPTY_BODY", "-Wempty-body")
          .put("CLANG_WARN_ENUM_CONVERSION", "-Wenum-conversion")
          .put("CLANG_WARN_INT_CONVERSION", "-Wint-conversion")
          .put("CLANG_WARN_UNREACHABLE_CODE", "-Wunreachable-code")
          .put("GCC_WARN_ABOUT_RETURN_TYPE", "-Wmismatched-return-types")
          .put("GCC_WARN_UNDECLARED_SELECTOR", "-Wundeclared-selector")
          .put("GCC_WARN_UNINITIALIZED_AUTOS", "-Wuninitialized")
          .put("GCC_WARN_UNUSED_FUNCTION", "-Wunused-function")
          .put("GCC_WARN_UNUSED_VARIABLE", "-Wunused-variable")
          .build();

  /** Returns the platform directory inside of Xcode for a platform name. */
  public static String platformDir(String platformName) {
    return developerDir() + "/Platforms/" + platformName + ".platform";
  }

  /**
   * Returns the platform directory inside of Xcode for a given configuration.
   */
  public static String sdkDir() {
    return SDKROOT_DIR;
  }

  /**
   * Returns the Developer directory inside of Xcode for a given configuration.
   */
  public static String developerDir() {
    return DEVELOPER_DIR;
  }

  /**
   * Returns the platform frameworks directory inside of Xcode for a given configuration.
   */
  public static String platformDeveloperFrameworkDir(AppleConfiguration configuration) {
    return platformDeveloperFrameworkDir(configuration.getSingleArchPlatform());
  }

  /**
   * Returns the platform frameworks directory inside of Xcode for a given {@link ApplePlatform}.
   */
  public static String platformDeveloperFrameworkDir(ApplePlatform platform) {
    String platformDir = platformDir(platform.getNameInPlist());
    return platformDir + "/Developer/Library/Frameworks";
  }

  /** Returns the SDK frameworks directory inside of Xcode for a given configuration. */
  public static String sdkFrameworkDir(
      ApplePlatform targetPlatform, RuleContext ruleContext) {
    String relativePath;
    switch (targetPlatform) {
      case IOS_DEVICE:
      case IOS_SIMULATOR:
        if (XcodeConfig.getSdkVersionForPlatform(ruleContext, targetPlatform)
            .compareTo(DottedVersion.fromString("9.0")) >= 0) {
          relativePath = SYSTEM_FRAMEWORK_PATH;
        } else {
          relativePath = DEVELOPER_FRAMEWORK_PATH;
        }
        break;
      case MACOS:
      case WATCHOS_DEVICE:
      case WATCHOS_SIMULATOR:
      case TVOS_DEVICE:
      case TVOS_SIMULATOR:
        relativePath = SYSTEM_FRAMEWORK_PATH;
        break;
      default:
        throw new IllegalArgumentException("Unhandled platform " + targetPlatform);
    }
    return sdkDir() + relativePath;
  }

  /** The default label of the build-wide {@code xcode_config} configuration rule. */
  public static LabelLateBoundDefault<AppleConfiguration> getXcodeConfigLabel(
      String toolsRepository) {
    return LabelLateBoundDefault.fromTargetConfiguration(
        AppleConfiguration.class,
        Label.parseAbsoluteUnchecked(
            toolsRepository + AppleCommandLineOptions.DEFAULT_XCODE_VERSION_CONFIG_LABEL),
        (Attribute.LateBoundDefault.Resolver<AppleConfiguration, Label> & Serializable)
            (rule, attributes, appleConfig) -> appleConfig.getXcodeConfigLabel());
  }

  /**
   * Returns the platform directory inside of Xcode for a given configuration.
   */
  @Override
  public String sdkDirConstant() {
    return sdkDir();
  }

  /**
   * Returns the Developer directory inside of Xcode for a given configuration.
   */
  @Override
  public String developerDirConstant() {
    return developerDir();
  }

  /**
   * Returns the platform frameworks directory inside of Xcode for a given configuration.
   */
  @Override
  public String platformFrameworkDirFromConfig(AppleConfiguration configuration) {
    return platformDeveloperFrameworkDir(configuration);
  }

  /**
   * Base rule definition to be ancestor for rules which may require an xcode toolchain.
   */
  public static class RequiresXcodeConfigRule implements RuleDefinition {
    private final String toolsRepository;

    public RequiresXcodeConfigRule(String toolsRepository) {
      this.toolsRepository = toolsRepository;
    }

    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(
              attr(XcodeConfigRule.XCODE_CONFIG_ATTR_NAME, LABEL)
                  .allowedRuleClasses("xcode_config")
                  .checkConstraints()
                  .direct_compile_time_input()
                  .value(getXcodeConfigLabel(toolsRepository)))
          .build();
    }
    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$requires_xcode_config")
          .type(RuleClassType.ABSTRACT)
          .build();
    }
  }
}
