// Copyright 2016 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.objc;

import static com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions.INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.starlark.StarlarkRuleContext;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.Provider;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.StarlarkInfo;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.ApplePlatform;
import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType;
import com.google.devtools.build.lib.rules.apple.DottedVersion;
import com.google.devtools.build.lib.rules.apple.XcodeVersionProperties;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcModule;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.cpp.UserVariablesExtension;
import com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag;
import com.google.devtools.build.lib.starlarkbuildapi.objc.AppleCommonApi;
import java.util.Map;
import javax.annotation.Nullable;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkFunction;
import net.starlark.java.eval.StarlarkInt;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
import net.starlark.java.eval.StarlarkValue;
import net.starlark.java.syntax.Location;

/** A class that exposes apple rule implementation internals to Starlark. */
public class AppleStarlarkCommon
    implements AppleCommonApi<
        Artifact,
        ConstraintValueInfo,
        StarlarkRuleContext,
        CcInfo,
        ObjcProvider,
        XcodeConfigInfo,
        ApplePlatform> {

  @VisibleForTesting
  public static final String DEPRECATED_KEY_ERROR =
      "Key '%s' no longer supported in ObjcProvider (use CcInfo instead).";

  @VisibleForTesting
  public static final String BAD_KEY_ERROR =
      "Argument %s not a recognized key, 'strict_include', or 'providers'.";

  @VisibleForTesting
  public static final String BAD_PROVIDERS_ITER_ERROR =
      "Value for argument 'providers' must be a list of ObjcProvider instances, instead found %s.";

  @VisibleForTesting
  public static final String BAD_PROVIDERS_ELEM_ERROR =
      "Value for argument 'providers' must be a list of ObjcProvider instances, instead found "
          + "iterable with %s.";

  @VisibleForTesting
  public static final String NOT_SET_ERROR = "Value for key %s must be a set, instead found %s.";

  @VisibleForTesting
  public static final String DEPRECATED_OBJC_PROVIDER_ERROR = "Key 'objc' no longer needed in %s.";

  @VisibleForTesting
  public static final String REQUIRED_CC_INFO_ERROR = "Key 'cc_info' is required in %s.";

  @Nullable private StructImpl platformType;
  @Nullable private StructImpl platform;

  private final CppSemantics cppSemantics;

  public AppleStarlarkCommon(CppSemantics cppSemantics) {
    this.cppSemantics = cppSemantics;
  }

  @Override
  public AppleToolchain getAppleToolchain() {
    return new AppleToolchain();
  }

  @Override
  public StructImpl getPlatformTypeStruct() {
    if (platformType == null) {
      platformType = PlatformType.getStarlarkStruct();
    }
    return platformType;
  }

  @Override
  public StructImpl getPlatformStruct() {
    if (platform == null) {
      platform = ApplePlatform.getStarlarkStruct();
    }
    return platform;
  }

  @Override
  public Provider getXcodeVersionPropertiesConstructor() {
    return XcodeVersionProperties.STARLARK_CONSTRUCTOR;
  }

  @Override
  public Provider getXcodeVersionConfigConstructor() {
    return XcodeConfigInfo.PROVIDER;
  }

  @Override
  public Provider getObjcProviderConstructor() {
    return ObjcProvider.STARLARK_CONSTRUCTOR;
  }

  @Override
  public Provider getAppleDynamicFrameworkConstructor() {
    return AppleDynamicFrameworkInfo.STARLARK_CONSTRUCTOR;
  }

  @Override
  public Provider getAppleExecutableBinaryConstructor() {
    return AppleExecutableBinaryInfo.STARLARK_CONSTRUCTOR;
  }

  @Override
  public Provider getAppleDebugOutputsConstructor() {
    return AppleDebugOutputsInfo.STARLARK_CONSTRUCTOR;
  }

  @Override
  public ImmutableMap<String, String> getAppleHostSystemEnv(XcodeConfigInfo xcodeConfig) {
    return AppleConfiguration.getXcodeVersionEnv(xcodeConfig.getXcodeVersion());
  }

  @Override
  public ImmutableMap<String, String> getTargetAppleEnvironment(
      XcodeConfigInfo xcodeConfigApi, ApplePlatform platformApi) {
    XcodeConfigInfo xcodeConfig = xcodeConfigApi;
    ApplePlatform platform = (ApplePlatform) platformApi;
    return AppleConfiguration.appleTargetPlatformEnv(
        platform, xcodeConfig.getSdkVersionForPlatform(platform));
  }

  @Override
  // This method is registered statically for Starlark, and never called directly.
  public ObjcProvider newObjcProvider(Dict<String, Object> kwargs, StarlarkThread thread)
      throws EvalException {
    ObjcProvider.StarlarkBuilder resultBuilder =
        new ObjcProvider.StarlarkBuilder(thread.getSemantics());
    for (Map.Entry<String, Object> entry : kwargs.entrySet()) {
      ObjcProvider.Key<?> key = ObjcProvider.getStarlarkKeyForString(entry.getKey());
      if (key != null) {
        if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)
            && ObjcProvider.DEPRECATED_KEYS.contains(key)) {
          throw new EvalException(String.format(DEPRECATED_KEY_ERROR, key.getStarlarkKeyName()));
        }
        resultBuilder.addElementsFromStarlark(key, entry.getValue());
      } else {
        switch (entry.getKey()) {
          case "cc_library":
            if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
              throw new EvalException(
                  String.format(DEPRECATED_KEY_ERROR, key.getStarlarkKeyName()));
            }
            CcModule.checkPrivateStarlarkificationAllowlist(thread);
            resultBuilder.uncheckedAddTransitive(
                ObjcProvider.CC_LIBRARY,
                ObjcProviderStarlarkConverters.convertToJava(
                    ObjcProvider.CC_LIBRARY, entry.getValue()));
            break;
          case "flag":
            if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
              throw new EvalException(
                  String.format(DEPRECATED_KEY_ERROR, key.getStarlarkKeyName()));
            }
            resultBuilder.add(ObjcProvider.FLAG, Flag.USES_CPP);
            break;
          case "strict_include":
            resultBuilder.addStrictIncludeFromStarlark(entry.getValue());
            break;
          case "providers":
            resultBuilder.addProvidersFromStarlark(entry.getValue());
            break;
          default:
            throw Starlark.errorf(BAD_KEY_ERROR, entry.getKey());
        }
      }
    }
    return resultBuilder.build();
  }

  @Override
  public AppleDynamicFrameworkInfo newDynamicFrameworkProvider(
      Object dylibBinary,
      Object depsCcInfo,
      Object depsObjcProvider,
      Object dynamicFrameworkDirs,
      Object dynamicFrameworkFiles,
      StarlarkThread thread)
      throws EvalException {
    NestedSet<String> frameworkDirs =
        Depset.noneableCast(dynamicFrameworkDirs, String.class, "framework_dirs");
    NestedSet<Artifact> frameworkFiles =
        Depset.noneableCast(dynamicFrameworkFiles, Artifact.class, "framework_files");
    Artifact binary = (dylibBinary != Starlark.NONE) ? (Artifact) dylibBinary : null;
    // TODO(b/252909384): Disallow Starlark.NONE once rules have been migrated to supply CcInfo.
    CcInfo ccInfo;
    if (depsCcInfo != Starlark.NONE) {
      ccInfo = (CcInfo) depsCcInfo;
    } else {
      if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
        throw new EvalException(String.format(REQUIRED_CC_INFO_ERROR, "AppleDynamicFrameworkInfo"));
      }
      ccInfo = CcInfo.EMPTY;
    }
    ObjcProvider objcProvider;
    if (depsObjcProvider != Starlark.NONE) {
      if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
        throw new EvalException(
            String.format(DEPRECATED_OBJC_PROVIDER_ERROR, "AppleDynamicFrameworkInfo"));
      }
      objcProvider = (ObjcProvider) depsObjcProvider;
    } else {
      objcProvider = new ObjcProvider.StarlarkBuilder(thread.getSemantics()).build();
    }
    return new AppleDynamicFrameworkInfo(
        binary, ccInfo, objcProvider, frameworkDirs, frameworkFiles);
  }

  @Override
  public AppleExecutableBinaryInfo newExecutableBinaryProvider(
      Object executableBinary, Object depsCcInfo, Object depsObjcProvider, StarlarkThread thread)
      throws EvalException {
    Artifact binary = (executableBinary != Starlark.NONE) ? (Artifact) executableBinary : null;
    // TODO(b/252909384): Disallow Starlark.NONE once rules have been migrated to supply CcInfo.
    CcInfo ccInfo;
    if (depsCcInfo != Starlark.NONE) {
      ccInfo = (CcInfo) depsCcInfo;
    } else {
      if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
        throw new EvalException(String.format(REQUIRED_CC_INFO_ERROR, "AppleExecutableBinaryInfo"));
      }
      ccInfo = CcInfo.EMPTY;
    }
    ObjcProvider objcProvider;
    if (depsObjcProvider != Starlark.NONE) {
      if (thread.getSemantics().getBool(INCOMPATIBLE_OBJC_PROVIDER_REMOVE_LINKING_INFO)) {
        throw new EvalException(
            String.format(DEPRECATED_OBJC_PROVIDER_ERROR, "AppleExecutableBinaryInfo"));
      }
      objcProvider = (ObjcProvider) depsObjcProvider;
    } else {
      objcProvider = new ObjcProvider.StarlarkBuilder(thread.getSemantics()).build();
    }
    return new AppleExecutableBinaryInfo(binary, ccInfo, objcProvider);
  }

  private Dict<?, ?> asDict(Object o) {
    return o == Starlark.NONE ? Dict.empty() : (Dict<?, ?>) o;
  }

  @Override
  public StructImpl linkMultiArchBinary(
      StarlarkRuleContext starlarkRuleContext,
      Object avoidDeps,
      Sequence<?> extraLinkopts,
      Sequence<?> extraLinkInputs,
      Sequence<?> extraRequestedFeatures,
      Sequence<?> extraDisabledFeatures,
      StarlarkInt stamp,
      Object variablesExtension,
      StarlarkThread thread)
      throws EvalException, InterruptedException {
    try {
      RuleContext ruleContext = starlarkRuleContext.getRuleContext();
      ImmutableList<TransitiveInfoCollection> avoidDepsList =
          (avoidDeps != Starlark.NONE)
              ? ImmutableList.copyOf(
                  Sequence.cast(avoidDeps, TransitiveInfoCollection.class, "avoid_deps"))
              : ImmutableList.of();
      boolean isStampingEnabled =
          isStampingEnabled(stamp.toInt("stamp"), ruleContext.getConfiguration());
      AppleLinkingOutputs linkingOutputs =
          AppleBinary.linkMultiArchBinary(
              ruleContext,
              cppSemantics,
              avoidDepsList,
              ImmutableList.copyOf(Sequence.cast(extraLinkopts, String.class, "extra_linkopts")),
              Sequence.cast(extraLinkInputs, Artifact.class, "extra_link_inputs"),
              Sequence.cast(extraRequestedFeatures, String.class, "extra_requested_features"),
              Sequence.cast(extraDisabledFeatures, String.class, "extra_disabled_features"),
              isStampingEnabled,
              new UserVariablesExtension(asDict(variablesExtension)));
      return createStarlarkLinkingOutputs(linkingOutputs, thread);
    } catch (RuleErrorException exception) {
      throw new EvalException(exception);
    }
  }

  @Override
  public StructImpl linkMultiArchStaticLibrary(
      StarlarkRuleContext starlarkRuleContext, StarlarkThread thread)
      throws EvalException, InterruptedException {
    try {
      RuleContext ruleContext = starlarkRuleContext.getRuleContext();
      StarlarkFunction linkMultiArchLibrary =
          (StarlarkFunction)
              ruleContext.getStarlarkDefinedBuiltin("link_multi_arch_static_library");
      Dict<String, StructImpl> splitTargetTriplets =
          MultiArchBinarySupport.getSplitTargetTripletFromCtads(
              ruleContext.getSplitPrerequisites(ObjcRuleClasses.CHILD_CONFIG_ATTR));
      return (StructImpl)
          ruleContext.callStarlarkOrThrowRuleError(
              linkMultiArchLibrary,
              ImmutableList.of(),
              ImmutableMap.of(
                  "ctx",
                  ruleContext.getStarlarkRuleContext(),
                  "split_target_triplets",
                  splitTargetTriplets));
    } catch (RuleErrorException exception) {
      throw new EvalException(exception);
    }
  }

  @Override
  public DottedVersion dottedVersion(String version) throws EvalException {
    try {
      return DottedVersion.fromString(version);
    } catch (DottedVersion.InvalidDottedVersionException e) {
      throw new EvalException(e.getMessage());
    }
  }

  /**
   * Returns the given value unless it is null, in which case the Starlark value {@code NONE} is
   * returned.
   */
  private Object valueOrNone(Object value) {
    if (value != null) {
      return value;
    }
    return Starlark.NONE;
  }

  /**
   * Creates a Starlark struct that contains the results of the {@code link_multi_arch_binary}
   * function.
   */
  private StructImpl createStarlarkLinkingOutputs(
      AppleLinkingOutputs linkingOutputs, StarlarkThread thread) {
    Provider linkingOutputConstructor =
        new BuiltinProvider<StructImpl>("apple_linking_output", StructImpl.class) {};
    ImmutableList.Builder<StarlarkInfo> outputStructs = ImmutableList.builder();

    for (AppleLinkingOutputs.LinkingOutput linkingOutput : linkingOutputs.getOutputs()) {
      AppleLinkingOutputs.TargetTriplet targetTriplet = linkingOutput.getTargetTriplet();
      outputStructs.add(
          StarlarkInfo.create(
              linkingOutputConstructor,
              ImmutableMap.<String, Object>builder()
                  .put("platform", targetTriplet.platform())
                  .put("architecture", targetTriplet.architecture())
                  .put("environment", targetTriplet.environment())
                  .put("binary", linkingOutput.getBinary())
                  .put("dsym_binary", valueOrNone(linkingOutput.getDsymBinary()))
                  .put("linkmap", valueOrNone(linkingOutput.getLinkmap()))
                  .buildOrThrow(),
              Location.BUILTIN));
    }

    // We have to transform the output group dictionary into one that contains StarlarkValues
    // instead of plain NestedSets because the Starlark caller may want to return this directly from
    // their implementation function.
    Map<String, StarlarkValue> outputGroups =
        Maps.transformValues(linkingOutputs.getOutputGroups(), v -> Depset.of(Artifact.class, v));

    ImmutableMap.Builder<String, Object> fields = ImmutableMap.builder();
    fields.put("objc", linkingOutputs.getDepsObjcProvider());
    fields.put("cc_info", linkingOutputs.getDepsCcInfo());
    fields.put("output_groups", Dict.copyOf(thread.mutability(), outputGroups));
    fields.put("outputs", StarlarkList.copyOf(thread.mutability(), outputStructs.build()));

    // TODO(b/110264170): Remove this field after clients have been migrated to use a provider
    // defined in Starlark and propagated by rules_apple instead.
    fields.put("debug_outputs_provider", linkingOutputs.getLegacyDebugOutputsProvider());

    Provider linkingOutputsConstructor =
        new BuiltinProvider<StructImpl>("apple_linking_outputs", StructImpl.class) {};
    return StarlarkInfo.create(linkingOutputsConstructor, fields.buildOrThrow(), Location.BUILTIN);
  }

  private static boolean isStampingEnabled(int stamp, BuildConfigurationValue config)
      throws EvalException {
    if (stamp == 0) {
      return false;
    }
    if (stamp == 1) {
      return true;
    }
    if (stamp == -1) {
      return config.stampBinaries();
    }
    throw Starlark.errorf(
        "stamp value %d is not supported; must be 0 (disabled), 1 (enabled), or -1 (default)",
        stamp);
  }
}
