// Copyright 2018 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.android;

import com.google.common.annotations.VisibleForTesting;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
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.collect.nestedset.Order;

/**
 * Contains transitive asset dependencies for a target.
 *
 * <p>In addition to NestedSets of transitive artifacts, we also keep transitive NestedSets of
 * direct and transitive parsed assets. These NestedSets contain the same information (and it may
 * appear in both the direct and transitive parsed asset NestedSets); we need to keep them both
 * separately to record relationships between assets, asset directories, and symbol artifacts and to
 * distinguish between direct and transitive assets.
 */
public class AssetDependencies {
  private final boolean neverlink;
  private final NestedSet<ParsedAndroidAssets> directParsedAssets;
  private final NestedSet<ParsedAndroidAssets> transitiveParsedAssets;
  private final NestedSet<Artifact> transitiveAssets;
  private final NestedSet<Artifact> transitiveSymbols;
  private final NestedSet<Artifact> transitiveCompiledSymbols;

  public static AssetDependencies fromRuleDeps(RuleContext ruleContext, boolean neverlink) {
    return fromProviders(
        AndroidCommon.getTransitivePrerequisites(
            ruleContext, Mode.TARGET, AndroidAssetsInfo.PROVIDER),
        neverlink);
  }

  public static AssetDependencies fromProviders(
      Iterable<AndroidAssetsInfo> providers, boolean neverlink) {
    NestedSetBuilder<ParsedAndroidAssets> direct = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<ParsedAndroidAssets> transitive = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<Artifact> assets = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<Artifact> symbols = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<Artifact> compiledSymbols = NestedSetBuilder.naiveLinkOrder();

    for (AndroidAssetsInfo info : providers) {
      direct.addTransitive(info.getDirectParsedAssets());
      transitive.addTransitive(info.getTransitiveParsedAssets());
      assets.addTransitive(info.getAssets());
      symbols.addTransitive(info.getSymbols());
      compiledSymbols.addTransitive(info.getCompiledSymbols());
    }

    return of(
        neverlink,
        direct.build(),
        transitive.build(),
        assets.build(),
        symbols.build(),
        compiledSymbols.build());
  }

  public static AssetDependencies empty() {
    return of(
        false,
        NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
        NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
        NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
        NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
        NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER));
  }

  @VisibleForTesting
  static AssetDependencies of(
      boolean neverlink,
      NestedSet<ParsedAndroidAssets> directParsedAssets,
      NestedSet<ParsedAndroidAssets> transitiveParsedAssets,
      NestedSet<Artifact> transitiveAssets,
      NestedSet<Artifact> transitiveSymbols,
      NestedSet<Artifact> transitiveCompiledSymbols) {
    return new AssetDependencies(
        neverlink,
        directParsedAssets,
        transitiveParsedAssets,
        transitiveAssets,
        transitiveSymbols,
        transitiveCompiledSymbols);
  }

  private AssetDependencies(
      boolean neverlink,
      NestedSet<ParsedAndroidAssets> directParsedAssets,
      NestedSet<ParsedAndroidAssets> transitiveParsedAssets,
      NestedSet<Artifact> transitiveAssets,
      NestedSet<Artifact> transitiveSymbols,
      NestedSet<Artifact> transitiveCompiledSymbols) {
    this.neverlink = neverlink;
    this.directParsedAssets = directParsedAssets;
    this.transitiveParsedAssets = transitiveParsedAssets;
    this.transitiveAssets = transitiveAssets;
    this.transitiveSymbols = transitiveSymbols;
    this.transitiveCompiledSymbols = transitiveCompiledSymbols;
  }

  /** Creates a new AndroidAssetInfo using the passed assets as the direct dependency. */
  public AndroidAssetsInfo toInfo(MergedAndroidAssets assets) {
    if (neverlink) {
      return AndroidAssetsInfo.empty(assets.getLabel());
    }

    NestedSet<ParsedAndroidAssets> updatedTransitiveParsedAssets =
        NestedSetBuilder.<ParsedAndroidAssets>naiveLinkOrder()
            .addTransitive(transitiveParsedAssets)
            .addTransitive(directParsedAssets)
            .build();

    if (assets.getAssets().isEmpty()) {
      return AndroidAssetsInfo.of(
          assets.getLabel(),
          // Even though no new assets were added, we should still make merging output available so
          // callers can ensure validation succeeded.
          assets.getMergedAssets(),
          NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER),
          updatedTransitiveParsedAssets,
          transitiveAssets,
          transitiveSymbols,
          transitiveCompiledSymbols);
    }

    // Create a new object to avoid passing around unwanted merge information to the provider
    ParsedAndroidAssets parsedAssets = new ParsedAndroidAssets(assets);

    NestedSetBuilder<Artifact> transitiveCompiledSymbolsBuilder =
        NestedSetBuilder.<Artifact>naiveLinkOrder().addTransitive(transitiveCompiledSymbols);

    if (assets.getCompiledSymbols() != null) {
      transitiveCompiledSymbolsBuilder.add(assets.getCompiledSymbols());
    }

    return AndroidAssetsInfo.of(
        assets.getLabel(),
        assets.getMergedAssets(),
        NestedSetBuilder.create(Order.NAIVE_LINK_ORDER, parsedAssets),
        updatedTransitiveParsedAssets,
        NestedSetBuilder.<Artifact>naiveLinkOrder()
            .addTransitive(transitiveAssets)
            .addAll(assets.getAssets())
            .build(),
        NestedSetBuilder.<Artifact>naiveLinkOrder()
            .addTransitive(transitiveSymbols)
            .add(assets.getSymbols())
            .build(),
        transitiveCompiledSymbolsBuilder.build());
  }

  /** Creates a new AndroidAssetsInfo from this target's dependencies, without any local assets. */
  public AndroidAssetsInfo toInfo(Label label) {
    if (neverlink) {
      return AndroidAssetsInfo.empty(label);
    }

    return AndroidAssetsInfo.of(
        label,
        null,
        directParsedAssets,
        transitiveParsedAssets,
        transitiveAssets,
        transitiveSymbols,
        transitiveCompiledSymbols);
  }

  public NestedSet<ParsedAndroidAssets> getDirectParsedAssets() {
    return directParsedAssets;
  }

  public NestedSet<ParsedAndroidAssets> getTransitiveParsedAssets() {
    return transitiveParsedAssets;
  }

  public NestedSet<Artifact> getTransitiveAssets() {
    return transitiveAssets;
  }

  public NestedSet<Artifact> getTransitiveSymbols() {
    return transitiveSymbols;
  }

  public NestedSet<Artifact> getTransitiveCompiledSymbols() {
    return transitiveCompiledSymbols;
  }
}
