// 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.cpp.proto;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode.TARGET;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMap;
import com.google.devtools.build.lib.analysis.TransitiveInfoProviderMapBuilder;
import com.google.devtools.build.lib.cmdline.Label;
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.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.cpp.AspectLegalCppSemantics;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper;
import com.google.devtools.build.lib.rules.cpp.CcLinkingOutputs;
import com.google.devtools.build.lib.rules.cpp.CcNativeLibraryProvider;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppDebugFileProvider;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.rules.proto.ProtoCommon;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.Exports;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.Services;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder.ToolchainInvocation;
import com.google.devtools.build.lib.rules.proto.ProtoConfiguration;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainProvider;
import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/** Part of the implementation of cc_proto_library. */
public abstract class CcProtoAspect extends NativeAspectClass implements ConfiguredAspectFactory {

  private static final String PROTO_TOOLCHAIN_ATTR = ":aspect_cc_proto_toolchain";

  private static final LabelLateBoundDefault<?> PROTO_TOOLCHAIN_LABEL =
      LabelLateBoundDefault.fromTargetConfiguration(
          ProtoConfiguration.class,
          Label.parseAbsoluteUnchecked("@com_google_protobuf//:cc_toolchain"),
          (rule, attributes, protoConfig) -> protoConfig.protoToolchainForCc());

  private final CppSemantics cppSemantics;
  private final LabelLateBoundDefault<?> ccToolchainAttrValue;
  private final Label ccToolchainType;

  protected CcProtoAspect(AspectLegalCppSemantics cppSemantics, RuleDefinitionEnvironment env) {
    this.cppSemantics = cppSemantics;
    this.ccToolchainAttrValue = CppRuleClasses.ccToolchainAttribute(env);
    this.ccToolchainType = CppRuleClasses.ccToolchainTypeAttribute(env);
  }

  @Override
  public ConfiguredAspect create(
      ConfiguredTargetAndData ctadBase,
      RuleContext ruleContext,
      AspectParameters parameters,
      String toolsRepository)
      throws InterruptedException, ActionConflictException {
    ProtoInfo protoInfo = checkNotNull(ctadBase.getConfiguredTarget().get(ProtoInfo.PROVIDER));

    try {
      ConfiguredAspect.Builder result = new ConfiguredAspect.Builder(this, parameters, ruleContext);
      new Impl(ruleContext, protoInfo, cppSemantics).addProviders(result);
      return result.build();
    } catch (RuleErrorException e) {
      ruleContext.ruleError(e.getMessage());
      return null;
    }
  }

  @Override
  public AspectDefinition getDefinition(AspectParameters aspectParameters) {
    AspectDefinition.Builder result =
        new AspectDefinition.Builder(this)
            .propagateAlongAttribute("deps")
            .requiresConfigurationFragments(CppConfiguration.class, ProtoConfiguration.class)
            .requireSkylarkProviders(ProtoInfo.PROVIDER.id())
            .addRequiredToolchains(ccToolchainType)
            .add(
                attr(PROTO_TOOLCHAIN_ATTR, LABEL)
                    .mandatoryNativeProviders(ImmutableList.of(ProtoLangToolchainProvider.class))
                    .value(PROTO_TOOLCHAIN_LABEL))
            .add(
                attr(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, LABEL)
                    .mandatoryProviders(CcToolchainProvider.PROVIDER.id())
                    .value(ccToolchainAttrValue));

    return result.build();
  }

  private static class Impl {

    private final TransitiveInfoProviderMap ccLibraryProviders;
    private final ProtoCcHeaderProvider headerProvider;
    private final ImmutableMap<String, NestedSet<Artifact>> outputGroups;

    private final RuleContext ruleContext;
    private final ProtoInfo protoInfo;
    private final CppSemantics cppSemantics;
    private final NestedSetBuilder<Artifact> filesBuilder;

    Impl(RuleContext ruleContext, ProtoInfo protoInfo, CppSemantics cppSemantics)
        throws RuleErrorException, InterruptedException {
      this.ruleContext = ruleContext;
      this.protoInfo = protoInfo;
      this.cppSemantics = cppSemantics;
      FeatureConfiguration featureConfiguration = getFeatureConfiguration();
      ProtoConfiguration protoConfiguration = ruleContext.getFragment(ProtoConfiguration.class);

      ImmutableList.Builder<TransitiveInfoCollection> depsBuilder = ImmutableList.builder();
      TransitiveInfoCollection runtime = getProtoToolchainProvider().runtime();
      if (runtime != null) {
        depsBuilder.add(runtime);
      }
      depsBuilder.addAll(ruleContext.getPrerequisites("deps", TARGET));
      ImmutableList<TransitiveInfoCollection> deps = depsBuilder.build();

      CppHelper.checkProtoLibrariesInDeps(ruleContext, deps);
      CcCompilationHelper compilationHelper =
          initializeCompilationHelper(featureConfiguration, deps);

      // Compute and register files generated by this proto library.
      Collection<Artifact> outputs = new ArrayList<>();
      if (areSrcsBlacklisted()) {
        registerBlacklistedSrcs(protoInfo, compilationHelper);
        headerProvider = null;
      } else if (!protoInfo.getDirectProtoSources().isEmpty()) {
        Collection<Artifact> headers =
            getOutputFiles(protoConfiguration.ccProtoLibraryHeaderSuffixes());
        Collection<Artifact> sources =
            getOutputFiles(protoConfiguration.ccProtoLibrarySourceSuffixes());
        outputs.addAll(headers);
        outputs.addAll(sources);

        compilationHelper.addSources(sources);
        compilationHelper.addPublicHeaders(headers);

        NestedSetBuilder<Artifact> publicHeaderPaths = NestedSetBuilder.stableOrder();
        publicHeaderPaths.addAll(headers);
        headerProvider = new ProtoCcHeaderProvider(publicHeaderPaths.build());
      } else {
        // If this proto_library doesn't have sources, it provides the combined headers of all its
        // direct dependencies. Thus, if a direct dependency does have sources, the generated files
        // are also provided by this library. If a direct dependency does not have sources, it will
        // do the same thing, so that effectively this library looks through all source-less
        // proto_libraries and provides all generated headers of the proto_libraries with sources
        // that it depends on.
        NestedSetBuilder<Artifact> transitiveHeaders = NestedSetBuilder.stableOrder();
        for (ProtoCcHeaderProvider provider :
            ruleContext.getPrerequisites("deps", TARGET, ProtoCcHeaderProvider.class)) {
          compilationHelper.addPublicTextualHeaders(provider.getHeaders());
          transitiveHeaders.addTransitive(provider.getHeaders());
        }
        headerProvider = new ProtoCcHeaderProvider(transitiveHeaders.build());
      }

      filesBuilder = NestedSetBuilder.stableOrder();
      filesBuilder.addAll(outputs);
      createProtoCompileAction(outputs);

      CompilationInfo compilationInfo = compilationHelper.compile();
      CcCompilationOutputs ccCompilationOutputs = compilationInfo.getCcCompilationOutputs();
      CcLinkingHelper ccLinkingHelper = initializeLinkingHelper(featureConfiguration, deps);
      if (ccToolchain(ruleContext).supportsInterfaceSharedLibraries(featureConfiguration)) {
        ccLinkingHelper.emitInterfaceSharedLibraries(true);
      }

      ImmutableList<LibraryToLink> libraryToLink = ImmutableList.of();
      if (!ccCompilationOutputs.isEmpty()) {
        CcLinkingOutputs ccLinkingOutputs = ccLinkingHelper.link(ccCompilationOutputs);
        if (!ccLinkingOutputs.isEmpty()) {
          libraryToLink = ImmutableList.of(ccLinkingOutputs.getLibraryToLink());
        }
      }
      CcNativeLibraryProvider ccNativeLibraryProvider =
          CppHelper.collectNativeCcLibraries(deps, libraryToLink);
      CcLinkingContext ccLinkingContext =
          ccLinkingHelper.buildCcLinkingContextFromLibrariesToLink(
              libraryToLink, compilationInfo.getCcCompilationContext());

      CppDebugFileProvider cppDebugFileProvider =
          CcCompilationHelper.buildCppDebugFileProvider(
              compilationInfo.getCcCompilationOutputs(), deps);
      ccLibraryProviders =
          new TransitiveInfoProviderMapBuilder()
              .add(cppDebugFileProvider)
              .put(
                  CcInfo.builder()
                      .setCcCompilationContext(compilationInfo.getCcCompilationContext())
                      .setCcLinkingContext(ccLinkingContext)
                      .build())
              .add(ccNativeLibraryProvider)
              .build();
      outputGroups =
          ImmutableMap.copyOf(
              CcCompilationHelper.buildOutputGroups(compilationInfo.getCcCompilationOutputs()));
      // On Windows, dynamic library is not built by default, so don't add them to filesToBuild.

      if (!libraryToLink.isEmpty()) {
        LibraryToLink artifactsToBuild = libraryToLink.get(0);
        if (artifactsToBuild.getStaticLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getStaticLibrary());
        }
        if (artifactsToBuild.getPicStaticLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getPicStaticLibrary());
        }
        if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
          if (artifactsToBuild.getResolvedSymlinkDynamicLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getResolvedSymlinkDynamicLibrary());
          } else if (artifactsToBuild.getDynamicLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getDynamicLibrary());
          }
          if (artifactsToBuild.getResolvedSymlinkInterfaceLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getResolvedSymlinkInterfaceLibrary());
          } else if (artifactsToBuild.getInterfaceLibrary() != null) {
            filesBuilder.add(artifactsToBuild.getInterfaceLibrary());
          }
        }
      }
    }

    private boolean areSrcsBlacklisted() {
      return !new ProtoSourceFileBlacklist(
              ruleContext, getProtoToolchainProvider().blacklistedProtos())
          .checkSrcs(protoInfo.getDirectProtoSources(), "cc_proto_library");
    }

    private FeatureConfiguration getFeatureConfiguration() {
      ImmutableSet.Builder<String> requestedFeatures = new ImmutableSet.Builder<>();
      requestedFeatures.addAll(ruleContext.getFeatures());
      ImmutableSet.Builder<String> unsupportedFeatures = new ImmutableSet.Builder<>();
      unsupportedFeatures.addAll(ruleContext.getDisabledFeatures());
      unsupportedFeatures.add(CppRuleClasses.PARSE_HEADERS);
      unsupportedFeatures.add(CppRuleClasses.LAYERING_CHECK);
      if (!areSrcsBlacklisted() && !protoInfo.getDirectProtoSources().isEmpty()) {
        requestedFeatures.add(CppRuleClasses.HEADER_MODULES);
      } else {
        unsupportedFeatures.add(CppRuleClasses.HEADER_MODULES);
      }
      FeatureConfiguration featureConfiguration =
          CcCommon.configureFeaturesOrReportRuleError(
              ruleContext,
              requestedFeatures.build(),
              unsupportedFeatures.build(),
              ccToolchain(ruleContext));
      return featureConfiguration;
    }

    private CcCompilationHelper initializeCompilationHelper(
        FeatureConfiguration featureConfiguration, List<TransitiveInfoCollection> deps) {
      CcToolchainProvider toolchain = ccToolchain(ruleContext);
      CcCompilationHelper helper =
          new CcCompilationHelper(
                  ruleContext,
                  ruleContext,
                  ruleContext.getLabel(),
                  CppHelper.getGrepIncludes(ruleContext),
                  cppSemantics,
                  featureConfiguration,
                  toolchain,
                  toolchain.getFdoContext())
              .addCcCompilationContexts(CppHelper.getCompilationContextsFromDeps(deps))
              .addCcCompilationContexts(
                  ImmutableList.of(CcCompilationHelper.getStlCcCompilationContext(ruleContext)));
      // Don't instrument the generated C++ files even when --collect_code_coverage is set.
      helper.setCodeCoverageEnabled(false);

      String protoRoot = protoInfo.getDirectProtoSourceRoot();
      PathFragment repositoryRoot =
          ruleContext.getLabel().getPackageIdentifier().getRepository().getSourceRoot();
      if (protoRoot.equals(".") || protoRoot.equals(repositoryRoot.getPathString())) {
        return helper;
      }

      PathFragment protoRootFragment = PathFragment.create(protoRoot);
      PathFragment binOrGenfiles = ruleContext.getBinOrGenfilesDirectory().getExecPath();
      if (protoRootFragment.startsWith(binOrGenfiles)) {
        protoRootFragment = protoRootFragment.relativeTo(binOrGenfiles);
      }
      PathFragment repositoryPath =
          ruleContext.getLabel().getPackageIdentifier().getRepository().getPathUnderExecRoot();
      if (protoRootFragment.startsWith(repositoryPath)) {
        protoRootFragment = protoRootFragment.relativeTo(repositoryPath);
      }

      String stripIncludePrefix =
          PathFragment.create("//").getRelative(protoRootFragment).toString();
      helper.setStripIncludePrefix(stripIncludePrefix);

      return helper;
    }

    private CcLinkingHelper initializeLinkingHelper(
        FeatureConfiguration featureConfiguration, ImmutableList<TransitiveInfoCollection> deps) {
      CcToolchainProvider toolchain = ccToolchain(ruleContext);
      CcLinkingHelper helper =
          new CcLinkingHelper(
                  ruleContext,
                  ruleContext.getLabel(),
                  ruleContext,
                  ruleContext,
                  cppSemantics,
                  featureConfiguration,
                  toolchain,
                  toolchain.getFdoContext(),
                  ruleContext.getConfiguration(),
                  ruleContext.getFragment(CppConfiguration.class),
                  ruleContext.getSymbolGenerator())
              .setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
              .setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget());
      helper.addCcLinkingContexts(CppHelper.getLinkingContextsFromDeps(deps));
      // TODO(dougk): Configure output artifact with action_config
      // once proto compile action is configurable from the crosstool.
      if (!toolchain.supportsDynamicLinker(featureConfiguration)) {
        helper.setShouldCreateDynamicLibrary(false);
      }
      return helper;
    }

    private static CcToolchainProvider ccToolchain(RuleContext ruleContext) {
      return CppHelper.getToolchain(
          ruleContext,
          ruleContext.getPrerequisite(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, TARGET));
    }

    private ImmutableSet<Artifact> getOutputFiles(Iterable<String> suffixes) {
      ImmutableSet.Builder<Artifact> result = ImmutableSet.builder();
      for (String suffix : suffixes) {
        result.addAll(
            ProtoCommon.getGeneratedOutputs(
                ruleContext, protoInfo.getDirectProtoSources(), suffix));
      }
      return result.build();
    }

    private void registerBlacklistedSrcs(ProtoInfo protoInfo, CcCompilationHelper helper) {
      // Hack: This is a proto_library for descriptor.proto or similar.
      //
      // The headers of those libraries are precomputed . They are also explicitly part of normal
      // cc_library rules that export them in their 'hdrs' attribute, and compile them as header
      // module if requested.
      //
      // The sole purpose of a proto_library with blacklisted srcs is so other proto_library rules
      // can import them from a protocol buffer, as proto_library rules can only depend on other
      // proto library rules.
      ImmutableList.Builder<PathFragment> headers = new ImmutableList.Builder<>();
      for (Artifact source : protoInfo.getDirectProtoSources()) {
        headers.add(FileSystemUtils.replaceExtension(source.getRootRelativePath(), ".pb.h"));
        headers.add(FileSystemUtils.replaceExtension(source.getRootRelativePath(), ".proto.h"));
      }
      // We add the header to the proto_library's module map as additional (textual) header for
      // two reasons:
      // 1. The header will be exported via a normal cc_library, and a header must only be exported
      //    non-textually from one library.
      // 2. We want to allow proto_library rules that depend on the bootstrap-hack proto_library
      //    to be layering-checked; we need to provide a module map for the layering check to work.
      helper.addAdditionalExportedHeaders(headers.build());
    }

    private void createProtoCompileAction(Collection<Artifact> outputs) {
      PathFragment protoRootFragment = PathFragment.create(protoInfo.getDirectProtoSourceRoot());
      String genfilesPath;
      PathFragment genfilesFragment = ruleContext.getConfiguration().getGenfilesFragment();
      if (protoRootFragment.startsWith(genfilesFragment)) {
        genfilesPath = protoRootFragment.getPathString();
      } else {
        genfilesPath = genfilesFragment.getRelative(protoRootFragment).getPathString();
      }

      ImmutableList.Builder<ToolchainInvocation> invocations = ImmutableList.builder();
      invocations.add(
          new ToolchainInvocation("C++", checkNotNull(getProtoToolchainProvider()), genfilesPath));
      ProtoCompileActionBuilder.registerActions(
          ruleContext,
          invocations.build(),
          protoInfo,
          ruleContext.getLabel(),
          outputs,
          "C++",
          Exports.DO_NOT_USE,
          Services.ALLOW);
    }

    private ProtoLangToolchainProvider getProtoToolchainProvider() {
      return ruleContext.getPrerequisite(
          PROTO_TOOLCHAIN_ATTR, TARGET, ProtoLangToolchainProvider.class);
    }

    public void addProviders(ConfiguredAspect.Builder builder) {
      OutputGroupInfo outputGroupInfo = new OutputGroupInfo(outputGroups);
      builder.addProvider(
          new CcProtoLibraryProviders(
              filesBuilder.build(), ccLibraryProviders, outputGroupInfo));
      builder.addProviders(ccLibraryProviders);
      builder.addNativeDeclaredProvider(outputGroupInfo);
      if (headerProvider != null) {
        builder.addProvider(headerProvider);
      }
    }
  }
}
