// 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.rules.objc.ObjcProvider.MULTI_ARCH_LINKED_ARCHIVES;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.actions.Artifact;
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.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.ApplePlatform.PlatformType;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.objc.ObjcProvider.Key;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Implementation for the "apple_static_library" rule.
 */
public class AppleStaticLibrary implements RuleConfiguredTargetFactory {

  /**
   * Set of {@link ObjcProvider} values which are propagated from dependencies to dependers by
   * this rule.
   */
  private static final ImmutableSet<Key<?>> PROPAGATE_KEYS =
      ImmutableSet.<Key<?>>of(
          ObjcProvider.ASSET_CATALOG,
          ObjcProvider.BUNDLE_FILE,
          ObjcProvider.SDK_DYLIB,
          ObjcProvider.SDK_FRAMEWORK,
          ObjcProvider.STORYBOARD,
          ObjcProvider.STRINGS,
          ObjcProvider.WEAK_SDK_FRAMEWORK,
          ObjcProvider.XCDATAMODEL,
          ObjcProvider.XIB,
          ObjcProvider.XCASSETS_DIR);

  @VisibleForTesting
  static final String UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT =
      "Unsupported platform type \"%s\"";

  @Override
  public final ConfiguredTarget create(RuleContext ruleContext)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    MultiArchSplitTransitionProvider.validateMinimumOs(ruleContext);
    PlatformType platformType = MultiArchSplitTransitionProvider.getPlatformType(ruleContext);

    ImmutableListMultimap<String, ConfiguredTargetAndData> cpuToCTATDepsCollectionMap =
        MultiArchBinarySupport.transformMap(
            ruleContext.getPrerequisiteCofiguredTargetAndTargetsByConfiguration(
                "deps", Mode.SPLIT));

    ImmutableListMultimap<String, ObjcProvider> cpuToObjcAvoidDepsMap =
        MultiArchBinarySupport.transformMap(
            ruleContext.getPrerequisitesByConfiguration(
                AppleStaticLibraryRule.AVOID_DEPS_ATTR_NAME,
                Mode.SPLIT,
                ObjcProvider.SKYLARK_CONSTRUCTOR));

    ImmutableListMultimap<String, CcInfo> cpuToCcAvoidDepsMap =
        MultiArchBinarySupport.transformMap(
            ruleContext.getPrerequisitesByConfiguration(
                AppleStaticLibraryRule.AVOID_DEPS_ATTR_NAME, Mode.SPLIT, CcInfo.PROVIDER));

    Iterable<ObjcProtoProvider> avoidProtoProviders =
        ruleContext.getPrerequisites(AppleStaticLibraryRule.AVOID_DEPS_ATTR_NAME, Mode.TARGET,
            ObjcProtoProvider.SKYLARK_CONSTRUCTOR);
    NestedSet<Artifact> protosToAvoid = protoArtifactsToAvoid(avoidProtoProviders);

    Map<BuildConfiguration, CcToolchainProvider> childConfigurationsAndToolchains =
        MultiArchBinarySupport.getChildConfigurationsAndToolchains(ruleContext);
    IntermediateArtifacts ruleIntermediateArtifacts =
        ObjcRuleClasses.intermediateArtifacts(ruleContext);

    NestedSetBuilder<Artifact> librariesToLipo =
        NestedSetBuilder.<Artifact>stableOrder();
    NestedSetBuilder<Artifact> filesToBuild =
        NestedSetBuilder.<Artifact>stableOrder()
            .add(ruleIntermediateArtifacts.combinedArchitectureArchive());

    ObjcProvider.Builder objcProviderBuilder =
        new ObjcProvider.Builder(ruleContext.getAnalysisEnvironment().getSkylarkSemantics());

    ImmutableListMultimap<BuildConfiguration, ObjcProtoProvider> objcProtoProvidersByConfig =
        ruleContext.getPrerequisitesByConfiguration(
            "deps", Mode.SPLIT, ObjcProtoProvider.SKYLARK_CONSTRUCTOR);
    Multimap<String, ObjcProtoProvider> objcProtoProvidersMap =
        MultiArchBinarySupport.transformMap(objcProtoProvidersByConfig);

    Map<String, NestedSet<Artifact>> outputGroupCollector = new TreeMap<>();
    for (Map.Entry<BuildConfiguration, CcToolchainProvider> entry :
        childConfigurationsAndToolchains.entrySet()) {
      BuildConfiguration childToolchainConfig = entry.getKey();
      String childCpu = entry.getKey().getCpu();
      CcToolchainProvider childToolchain = entry.getValue();
      Iterable<ObjcProtoProvider> objcProtoProviders = objcProtoProvidersMap.get(childCpu);
      ProtobufSupport protoSupport =
          new ProtobufSupport(
                  ruleContext,
                  childToolchainConfig,
                  protosToAvoid,
                  ImmutableList.<ProtoInfo>of(),
                  objcProtoProviders,
                  ProtobufSupport.getTransitivePortableProtoFilters(objcProtoProviders),
                  childToolchain)
              .registerGenerationActions()
              .registerCompilationActions();

      Optional<ObjcProvider> protosObjcProvider = protoSupport.getObjcProvider();

      IntermediateArtifacts intermediateArtifacts =
          ObjcRuleClasses.intermediateArtifacts(ruleContext, childToolchainConfig);

      ObjcCommon common =
          common(
              ruleContext,
              childToolchainConfig,
              intermediateArtifacts,
              nullToEmptyList(cpuToCTATDepsCollectionMap.get(childCpu)),
              protosObjcProvider);
      ObjcProvider objcProvider =
          common
              .getObjcProvider()
              .subtractSubtrees(
                  cpuToObjcAvoidDepsMap.get(childCpu),
                  cpuToCcAvoidDepsMap.get(childCpu).stream()
                      .map(CcInfo::getCcLinkingContext)
                      .collect(ImmutableList.toImmutableList()));

      librariesToLipo.add(intermediateArtifacts.strippedSingleArchitectureLibrary());

      CompilationSupport compilationSupport =
          new CompilationSupport.Builder()
              .setRuleContext(ruleContext)
              .setConfig(childToolchainConfig)
              .setToolchainProvider(childToolchain)
              .setOutputGroupCollector(outputGroupCollector)
              .build();

      compilationSupport
          .registerCompileAndArchiveActions(
              common.getCompilationArtifacts().get(), objcProvider, childToolchain)
          .registerFullyLinkAction(
              objcProvider,
              intermediateArtifacts.strippedSingleArchitectureLibrary(),
              childToolchain,
              childToolchain.getFdoContext())
          .validateAttributes();
      ruleContext.assertNoErrors();

      addTransitivePropagatedKeys(objcProviderBuilder, objcProvider);
    }

    AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);

    new LipoSupport(ruleContext)
        .registerCombineArchitecturesAction(
            librariesToLipo.build(),
            ruleIntermediateArtifacts.combinedArchitectureArchive(),
            appleConfiguration.getMultiArchPlatform(platformType));

    RuleConfiguredTargetBuilder targetBuilder =
        ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build());

    objcProviderBuilder.add(
        MULTI_ARCH_LINKED_ARCHIVES, ruleIntermediateArtifacts.combinedArchitectureArchive());

    ObjcProvider objcProvider = objcProviderBuilder.build();

    if (appleConfiguration.shouldLinkingRulesPropagateObjc()) {
      targetBuilder.addNativeDeclaredProvider(objcProvider);
    }

    targetBuilder
        .addNativeDeclaredProvider(
            new AppleStaticLibraryInfo(
                ruleIntermediateArtifacts.combinedArchitectureArchive(),
                objcProvider))
        .addOutputGroups(outputGroupCollector);
    return targetBuilder.build();
  }

  private void addTransitivePropagatedKeys(ObjcProvider.Builder objcProviderBuilder,
      ObjcProvider provider) {
    for (Key<?> key : PROPAGATE_KEYS) {
      objcProviderBuilder.addTransitiveAndPropagate(key, provider);
    }
  }

  private ObjcCommon common(
      RuleContext ruleContext,
      BuildConfiguration buildConfiguration,
      IntermediateArtifacts intermediateArtifacts,
      List<ConfiguredTargetAndData> propagatedConfigredTargetAndTargetDeps,
      Optional<ObjcProvider> protosObjcProvider) throws InterruptedException {

    CompilationArtifacts compilationArtifacts = new CompilationArtifacts.Builder().build();

    return new ObjcCommon.Builder(ruleContext, buildConfiguration)
        .setCompilationAttributes(
            CompilationAttributes.Builder.fromRuleContext(ruleContext).build())
        .setCompilationArtifacts(compilationArtifacts)
        .addDeps(propagatedConfigredTargetAndTargetDeps)
        .addDepObjcProviders(protosObjcProvider.asSet())
        .setIntermediateArtifacts(intermediateArtifacts)
        .setAlwayslink(false)
        .build();
  }

  private <T> List<T> nullToEmptyList(List<T> inputList) {
    return inputList != null ? inputList : ImmutableList.<T>of();
  }

  private static NestedSet<Artifact> protoArtifactsToAvoid(
      Iterable<ObjcProtoProvider> avoidedProviders) {
    NestedSetBuilder<Artifact> avoidArtifacts = NestedSetBuilder.stableOrder();
    for (ObjcProtoProvider avoidProvider : avoidedProviders) {
      for (NestedSet<Artifact> avoidProviderOutputGroup : avoidProvider.getProtoGroups()) {
        avoidArtifacts.addTransitive(avoidProviderOutputGroup);
      }
    }
    return avoidArtifacts.build();
  }
}
