// 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 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.actions.MutableActionGraph.ActionConflictException;
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.config.transitions.StarlarkExposedRuleTransitionFactory;
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.AppleToolchain;
import com.google.devtools.build.lib.rules.apple.DottedVersion;
import com.google.devtools.build.lib.rules.apple.XcodeConfigInfo;
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.objc.ObjcProvider.Flag;
import com.google.devtools.build.lib.starlarkbuildapi.SplitTransitionProviderApi;
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> {

  @Override
  public StarlarkExposedRuleTransitionFactory getAppleCrosstoolTransition() {
    return new AppleCrosstoolTransition.AppleCrosstoolTransitionFactory();
  }

  @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.";

  @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
  public SplitTransitionProviderApi getMultiArchSplitProvider() {
    return new MultiArchSplitTransitionProvider();
  }

  @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) {
        resultBuilder.addElementsFromStarlark(key, entry.getValue());
      } else {
        switch (entry.getKey()) {
          case "cc_library":
            CcModule.checkPrivateStarlarkificationAllowlist(thread);
            resultBuilder.uncheckedAddTransitive(
                ObjcProvider.CC_LIBRARY,
                ObjcProviderStarlarkConverters.convertToJava(
                    ObjcProvider.CC_LIBRARY, entry.getValue()));
            break;
          case "flag":
            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,
      ObjcProvider depsObjcProvider,
      Object dynamicFrameworkDirs,
      Object dynamicFrameworkFiles)
      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 = (depsCcInfo != Starlark.NONE) ? (CcInfo) depsCcInfo : CcInfo.EMPTY;

    return new AppleDynamicFrameworkInfo(
        binary, ccInfo, depsObjcProvider, frameworkDirs, frameworkFiles);
  }

  @Override
  public AppleExecutableBinaryInfo newExecutableBinaryProvider(
      Object executableBinary, Object depsCcInfo, ObjcProvider depsObjcProvider)
      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 = (depsCcInfo != Starlark.NONE) ? (CcInfo) depsCcInfo : CcInfo.EMPTY;
    return new AppleExecutableBinaryInfo(binary, ccInfo, depsObjcProvider);
  }

  @Override
  public StructImpl linkMultiArchBinary(
      StarlarkRuleContext starlarkRuleContext,
      Object avoidDeps,
      Sequence<?> extraLinkopts,
      Sequence<?> extraLinkInputs,
      StarlarkInt stamp,
      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"),
              isStampingEnabled);
      return createStarlarkLinkingOutputs(linkingOutputs, thread);
    } catch (RuleErrorException | ActionConflictException 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.getSplitPrerequisiteConfiguredTargetAndTargets(
                  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("bitcode_symbols", valueOrNone(linkingOutput.getBitcodeSymbols()))
                  .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.TYPE, 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);
  }
}
