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

import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FORCE_LOAD_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.J2OBJC_LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKOPT;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SOURCE;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.UMBRELLA_HEADER;
import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.HEADERS;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.OBJECT_FILE_SOURCES;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
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.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.rules.apple.AppleToolchain;
import com.google.devtools.build.lib.rules.cpp.CcCompilationContext;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.CppModuleMap;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.starlark.java.eval.StarlarkSemantics;
import net.starlark.java.eval.StarlarkValue;

/**
 * Contains information common to multiple objc_* rules, and provides a unified API for extracting
 * and accessing it.
 */
// TODO(bazel-team): Decompose and subsume area-specific logic and data into the various *Support
// classes. Make sure to distinguish rule output (providers, runfiles, ...) from intermediate,
// rule-internal information. Any provider created by a rule should not be read, only published.
public final class ObjcCommon implements StarlarkValue {

  /** Filters fileset artifacts out of a group of artifacts. */
  public static ImmutableList<Artifact> filterFileset(Iterable<Artifact> artifacts) {
    ImmutableList.Builder<Artifact> inputs = ImmutableList.<Artifact>builder();
    for (Artifact artifact : artifacts) {
      if (!artifact.isFileset()) {
        inputs.add(artifact);
      }
    }
    return inputs.build();
  }

  /**
   * Indicates the purpose the ObjcCommon is used for.
   *
   * <p>The purpose determines whether ObjcCommon.build() will build an ObjcProvider or an
   * ObjcProvider.Builder. In compile-and-link mode, ObjcCommon.build() will output an
   * ObjcProvider.Builder. The builder is expected to combine with the CcCompilationContext from a
   * compile action, to form a complete ObjcProvider. In link-only mode, ObjcCommon can (and does)
   * output the full ObjcProvider.
   */
  public enum Purpose {
    /** The ObjcCommon will be used for compile and link. */
    COMPILE_AND_LINK,
    /** The ObjcCommon will be used for linking only. */
    LINK_ONLY,
  }

  static class Builder {
    private final Purpose purpose;
    private final RuleContext context;
    private final StarlarkSemantics semantics;
    private final BuildConfigurationValue buildConfiguration;
    private Optional<CompilationAttributes> compilationAttributes = Optional.absent();
    private Optional<CompilationArtifacts> compilationArtifacts = Optional.absent();
    private Iterable<ObjcProvider> objcProviders = ImmutableList.of();
    private Iterable<PathFragment> includes = ImmutableList.of();
    private IntermediateArtifacts intermediateArtifacts;
    private boolean alwayslink;
    private Iterable<String> linkopts = ImmutableList.of();
    private boolean hasModuleMap;
    private Iterable<Artifact> extraImportLibraries = ImmutableList.of();
    private final List<CcCompilationContext> ccCompilationContexts = new ArrayList<>();
    private final List<CcLinkingContext> ccLinkingContexts = new ArrayList<>();
    private final List<CcCompilationContext> directCCompilationContexts = new ArrayList<>();
    // List of CcLinkingContext to be merged into ObjcProvider, to be done for deps that don't have
    // ObjcProviders.
    // TODO(b/171413861): remove after objc link info migration.
    private final List<CcLinkingContext> ccLinkingContextsForMerging = new ArrayList<>();

    /**
     * Builder for {@link ObjcCommon} obtaining both attribute data and configuration data from the
     * given rule context.
     */
    Builder(Purpose purpose, RuleContext context) throws InterruptedException {
      this(purpose, context, context.getConfiguration());
    }

    /**
     * Builder for {@link ObjcCommon} obtaining attribute data from the rule context and
     * configuration data from the given configuration object for use in situations where a single
     * target's outputs are under multiple configurations.
     */
    Builder(Purpose purpose, RuleContext context, BuildConfigurationValue buildConfiguration)
        throws InterruptedException {
      this.purpose = purpose;
      this.context = Preconditions.checkNotNull(context);
      this.semantics = context.getAnalysisEnvironment().getStarlarkSemantics();
      this.buildConfiguration = Preconditions.checkNotNull(buildConfiguration);
    }

    @CanIgnoreReturnValue
    public Builder setCompilationAttributes(CompilationAttributes baseCompilationAttributes) {
      Preconditions.checkState(
          !this.compilationAttributes.isPresent(),
          "compilationAttributes is already set to: %s",
          this.compilationAttributes);
      this.compilationAttributes = Optional.of(baseCompilationAttributes);
      return this;
    }

    @CanIgnoreReturnValue
    Builder setCompilationArtifacts(CompilationArtifacts compilationArtifacts) {
      Preconditions.checkState(
          !this.compilationArtifacts.isPresent(),
          "compilationArtifacts is already set to: %s",
          this.compilationArtifacts);
      this.compilationArtifacts = Optional.of(compilationArtifacts);
      return this;
    }

    @CanIgnoreReturnValue
    Builder addDirectCcCompilationContexts(Iterable<CcInfo> ccInfos) {
      // TODO(waltl): Support direct CcCompilationContexts in CcCompilationHelper.
      Preconditions.checkState(
          this.purpose.equals(Purpose.LINK_ONLY),
          "direct CcCompilationContext is only supported for LINK_ONLY purpose");
      ccInfos.forEach(ccInfo -> directCCompilationContexts.add(ccInfo.getCcCompilationContext()));
      return this;
    }

    @CanIgnoreReturnValue
    Builder addCcCompilationContexts(Iterable<CcInfo> ccInfos) {
      ccInfos.forEach(ccInfo -> ccCompilationContexts.add(ccInfo.getCcCompilationContext()));
      return this;
    }

    @CanIgnoreReturnValue
    Builder addCcLinkingContexts(Iterable<CcInfo> ccInfos) {
      ccInfos.forEach(ccInfo -> ccLinkingContexts.add(ccInfo.getCcLinkingContext()));
      return this;
    }

    @CanIgnoreReturnValue
    Builder addCcInfos(Iterable<CcInfo> ccInfos) {
      addCcCompilationContexts(ccInfos);
      addCcLinkingContexts(ccInfos);
      return this;
    }

    @CanIgnoreReturnValue
    Builder addDeps(List<? extends TransitiveInfoCollection> deps) {
      ImmutableList.Builder<ObjcProvider> objcProviders = ImmutableList.builder();
      ImmutableList.Builder<CcInfo> ccInfos = ImmutableList.builder();

      for (TransitiveInfoCollection dep : deps) {
        if (dep.get(ObjcProvider.STARLARK_CONSTRUCTOR) != null) {
          addAnyProviders(objcProviders, dep, ObjcProvider.STARLARK_CONSTRUCTOR);
        } else {
          // We only use CcInfo's linking info if there is no ObjcProvider.  This is required so
          // that objc_library archives do not get treated as if they are from cc targets.
          addAnyContexts(
              ccLinkingContextsForMerging, dep, CcInfo.PROVIDER, CcInfo::getCcLinkingContext);
        }
        addAnyProviders(ccInfos, dep, CcInfo.PROVIDER);
      }

      addObjcProviders(objcProviders.build());
      addCcInfos(ccInfos.build());

      return this;
    }

    @CanIgnoreReturnValue
    private static <T extends Info> ImmutableList.Builder<T> addAnyProviders(
        ImmutableList.Builder<T> listBuilder,
        TransitiveInfoCollection collection,
        BuiltinProvider<T> providerClass) {
      T provider = collection.get(providerClass);
      if (provider != null) {
        listBuilder.add(provider);
      }
      return listBuilder;
    }

    @CanIgnoreReturnValue
    private static <T extends Info, U> List<U> addAnyContexts(
        List<U> list,
        TransitiveInfoCollection collection,
        BuiltinProvider<T> providerClass,
        Function<T, U> getContext) {
      T provider = collection.get(providerClass);
      if (provider != null) {
        list.add(getContext.apply(provider));
      }
      return list;
    }

    /**
     * Add providers which will be exposed both to the declaring rule and to any dependers on the
     * declaring rule.
     */
    @CanIgnoreReturnValue
    Builder addObjcProviders(Iterable<ObjcProvider> objcProviders) {
      this.objcProviders = Iterables.concat(this.objcProviders, objcProviders);
      return this;
    }

    /** Adds includes to be passed into compile actions with {@code -I}. */
    @CanIgnoreReturnValue
    public Builder addIncludes(NestedSet<PathFragment> includes) {
      // The includes are copied to a new list in the .build() method, so flattening here should be
      // benign.
      this.includes = Iterables.concat(this.includes, includes.toList());
      return this;
    }

    /** Adds includes to be passed into compile actions with {@code -I}. */
    @CanIgnoreReturnValue
    public Builder addIncludes(Iterable<PathFragment> includes) {
      this.includes = Iterables.concat(this.includes, includes);
      return this;
    }

    @CanIgnoreReturnValue
    Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
      this.intermediateArtifacts = intermediateArtifacts;
      return this;
    }

    @CanIgnoreReturnValue
    Builder setAlwayslink(boolean alwayslink) {
      this.alwayslink = alwayslink;
      return this;
    }

    /**
     * Specifies that this target has a clang module map. This should be called if this target
     * compiles sources or exposes headers for other targets to use. Note that this does not add the
     * action to generate the module map. It simply indicates that it should be added to the
     * provider.
     */
    @CanIgnoreReturnValue
    Builder setHasModuleMap() {
      this.hasModuleMap = true;
      return this;
    }

    ObjcCommon build() {
      ImmutableList<CcCompilationContext> ccCompilationContexts =
          ImmutableList.copyOf(this.ccCompilationContexts);
      ImmutableList<CcLinkingContext> ccLinkingContexts =
          ImmutableList.copyOf(this.ccLinkingContexts);
      ImmutableList<CcCompilationContext> directCCompilationContexts =
          ImmutableList.copyOf(this.directCCompilationContexts);
      ImmutableList<CcLinkingContext> ccLinkingContextsForMerging =
          ImmutableList.copyOf(this.ccLinkingContextsForMerging);

      ObjcCompilationContext.Builder objcCompilationContextBuilder =
          ObjcCompilationContext.builder();

      ObjcProvider.Builder objcProvider = new ObjcProvider.Builder(semantics);

      objcProvider
          .addAll(IMPORTED_LIBRARY, extraImportLibraries)
          .addTransitiveAndPropagate(objcProviders);

      objcCompilationContextBuilder
          .addIncludes(includes)
          .addObjcProviders(objcProviders)
          .addDirectCcCompilationContexts(directCCompilationContexts)
          // TODO(bazel-team): This pulls in stl via
          // CcCompilationHelper.getStlCcCompilationContext(), but probably shouldn't.
          .addCcCompilationContexts(ccCompilationContexts);

      for (CcLinkingContext ccLinkingContext : ccLinkingContextsForMerging) {
        ImmutableList<String> linkOpts = ccLinkingContext.getFlattenedUserLinkFlags();
        if (!buildConfiguration.getFragment(ObjcConfiguration.class).linkingInfoMigration()) {
          addLinkoptsToObjcProvider(linkOpts, objcProvider);
        }
        objcProvider.addTransitiveAndPropagate(
            CC_LIBRARY,
            NestedSetBuilder.<LibraryToLink>linkOrder()
                .addTransitive(ccLinkingContext.getLibraries())
                .build());
      }
      addLinkoptsToObjcProvider(linkopts, objcProvider);

      if (compilationAttributes.isPresent()) {
        CompilationAttributes attributes = compilationAttributes.get();
        PathFragment usrIncludeDir = PathFragment.create(AppleToolchain.sdkDir() + "/usr/include/");
        Iterable<PathFragment> sdkIncludes =
            Iterables.transform(
                attributes.sdkIncludes().toList(), (p) -> usrIncludeDir.getRelative(p));
        objcProvider
            .addAll(SDK_FRAMEWORK, attributes.sdkFrameworks())
            .addAll(WEAK_SDK_FRAMEWORK, attributes.weakSdkFrameworks())
            .addAll(SDK_DYLIB, attributes.sdkDylibs());
        objcCompilationContextBuilder
            .addPublicHeaders(filterFileset(attributes.hdrs().toList()))
            .addPublicTextualHeaders(filterFileset(attributes.textualHdrs().toList()))
            .addDefines(attributes.defines())
            .addIncludes(
                attributes
                    .headerSearchPaths(
                        buildConfiguration.getGenfilesFragment(context.getRepository()))
                    .toList())
            .addIncludes(sdkIncludes);
      }

      for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) {
        Iterable<Artifact> allSources =
            Iterables.concat(
                FileType.except(artifacts.getSrcs(), OBJECT_FILE_SOURCES),
                artifacts.getNonArcSrcs());
        objcProvider
            .addAll(LIBRARY, artifacts.getArchive().asSet())
            .addAll(SOURCE, allSources)
            .addAllDirect(SOURCE, allSources);
        objcCompilationContextBuilder.addPublicHeaders(
            filterFileset(artifacts.getAdditionalHdrs()));
        objcCompilationContextBuilder.addPrivateHeaders(
            FileType.filter(artifacts.getSrcs(), HEADERS));

        if (artifacts.getArchive().isPresent()
            && J2ObjcLibrary.J2OBJC_SUPPORTED_RULES.contains(context.getRule().getRuleClass())) {
          objcProvider.addAll(J2OBJC_LIBRARY, artifacts.getArchive().asSet());
        }
      }

      if (alwayslink) {
        for (CompilationArtifacts artifacts : compilationArtifacts.asSet()) {
          for (Artifact archive : artifacts.getArchive().asSet()) {
            objcProvider.add(FORCE_LOAD_LIBRARY, archive);
          }
        }
        for (Artifact archive : extraImportLibraries) {
          objcProvider.add(FORCE_LOAD_LIBRARY, archive);
        }
      }

      if (hasModuleMap) {
        CppModuleMap moduleMap = intermediateArtifacts.swiftModuleMap();
        Optional<Artifact> umbrellaHeader = moduleMap.getUmbrellaHeader();
        if (umbrellaHeader.isPresent()) {
          objcProvider.add(UMBRELLA_HEADER, umbrellaHeader.get());
        }
        objcProvider.add(MODULE_MAP, moduleMap.getArtifact());
        objcProvider.addDirect(MODULE_MAP, moduleMap.getArtifact());
      }

      ObjcCompilationContext objcCompilationContext = objcCompilationContextBuilder.build();

      return new ObjcCommon(
          purpose,
          objcProvider.build(),
          objcCompilationContext,
          ccLinkingContexts,
          compilationArtifacts);
    }

    private void addLinkoptsToObjcProvider(
        Iterable<String> linkopts, ObjcProvider.Builder objcProvider) {
      ImmutableSet.Builder<String> frameworkLinkOpts = new ImmutableSet.Builder<>();
      ImmutableSet.Builder<String> weakFrameworkLinkOpts = new ImmutableSet.Builder<>();
      ImmutableList.Builder<String> nonFrameworkLinkOpts = new ImmutableList.Builder<>();
      // Add any framework flags as frameworks directly, rather than as linkopts.  Otherwise the
      // "-framework" flag can get incorrectly deduped.
      for (Iterator<String> iterator = linkopts.iterator(); iterator.hasNext(); ) {
        String arg = iterator.next();
        if (arg.equals("-framework") && iterator.hasNext()) {
          frameworkLinkOpts.add(iterator.next());
        } else if (arg.equals("-weak_framework") && iterator.hasNext()) {
          weakFrameworkLinkOpts.add(iterator.next());
        } else if (arg.startsWith("-Wl,-framework,")) {
          frameworkLinkOpts.add(arg.split(",", -1)[2]);
        } else if (arg.startsWith("-Wl,-weak_framework,")) {
          weakFrameworkLinkOpts.add(arg.split(",", -1)[2]);
        } else {
          nonFrameworkLinkOpts.add(arg);
        }
      }

      objcProvider
          .addAll(SDK_FRAMEWORK, frameworkLinkOpts.build())
          .addAll(WEAK_SDK_FRAMEWORK, weakFrameworkLinkOpts.build())
          .addAll(LINKOPT, nonFrameworkLinkOpts.build());
    }
  }

  private final Purpose purpose;
  private final ObjcProvider objcProvider;
  private final ObjcCompilationContext objcCompilationContext;
  private final ImmutableList<CcLinkingContext> ccLinkingContexts;

  private final Optional<CompilationArtifacts> compilationArtifacts;

  private ObjcCommon(
      Purpose purpose,
      ObjcProvider objcProvider,
      ObjcCompilationContext objcCompilationContext,
      ImmutableList<CcLinkingContext> ccLinkingContexts,
      Optional<CompilationArtifacts> compilationArtifacts) {
    this.purpose = purpose;
    this.objcProvider = Preconditions.checkNotNull(objcProvider);
    this.objcCompilationContext = Preconditions.checkNotNull(objcCompilationContext);
    this.ccLinkingContexts = Preconditions.checkNotNull(ccLinkingContexts);
    this.compilationArtifacts = Preconditions.checkNotNull(compilationArtifacts);
  }

  public Purpose getPurpose() {
    return purpose;
  }

  public ObjcProvider getObjcProvider() {
    return objcProvider;
  }

  public ObjcCompilationContext getObjcCompilationContext() {
    return objcCompilationContext;
  }

  public ImmutableList<CcLinkingContext> getCcLinkingContexts() {
    return ccLinkingContexts;
  }

  public Optional<CompilationArtifacts> getCompilationArtifacts() {
    return compilationArtifacts;
  }

  public CcCompilationContext createCcCompilationContext() {
    return objcCompilationContext.createCcCompilationContext();
  }

  public CcLinkingContext createCcLinkingContext() {
    return CcLinkingContext.merge(ccLinkingContexts);
  }

  public CcInfo createCcInfo() {
    return CcInfo.builder()
        .setCcCompilationContext(createCcCompilationContext())
        .setCcLinkingContext(createCcLinkingContext())
        .build();
  }

  /**
   * Returns an {@link Optional} containing the compiled {@code .a} file, or {@link
   * Optional#absent()} if this object contains no {@link CompilationArtifacts} or the compilation
   * information has no sources.
   */
  public Optional<Artifact> getCompiledArchive() {
    if (compilationArtifacts.isPresent()) {
      return compilationArtifacts.get().getArchive();
    }
    return Optional.absent();
  }
}
