// 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.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;

/** Wraps merged Android resources. */
public class MergedAndroidResources extends ParsedAndroidResources {
  private final Artifact mergedResources;
  private final Artifact classJar;
  @Nullable private final Artifact aapt2RTxt;
  @Nullable private final Artifact dataBindingInfoZip;
  private final ResourceDependencies resourceDependencies;
  /**
   * The processed manifest.
   *
   * <p>TODO(b/30817309): Just use the manifest inherited from {@link ParsedAndroidResources} once
   * the legacy manifest merger is removed.
   */
  private final ProcessedAndroidManifest manifest;

  public static MergedAndroidResources mergeFrom(
      AndroidDataContext dataContext,
      ParsedAndroidResources parsed,
      ResourceDependencies resourceDeps)
      throws InterruptedException {

    Preconditions.checkNotNull(
        parsed.getCompiledSymbols(),
        "Should not use compiled merge if no compiled symbols are available!");

    AndroidResourceMergingActionBuilder builder =
        new AndroidResourceMergingActionBuilder()
            .setJavaPackage(parsed.getJavaPackage())
            .withDependencies(resourceDeps)
            .setThrowOnResourceConflict(dataContext.throwOnResourceConflict())
            .setAnnotateRFieldsFromTransitiveDeps(dataContext.annotateRFieldsFromTransitiveDeps())
            .setOmitTransitiveDependenciesFromAndroidRClasses(
                dataContext.omitTransitiveResourcesFromAndroidRClasses());

    parsed.asDataBindingContext().supplyLayoutInfo(builder::setDataBindingInfoZip);

    if (dataContext.getAndroidConfig().useRTxtFromMergedResources()) {
      builder.setAapt2RTxtOut(
          dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_AAPT2_R_TXT));
    }

    return builder
        .setManifestOut(
            dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST))
        .setClassJarOut(
            dataContext.createOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_CLASS_JAR))
        .build(dataContext, parsed);
  }

  public static MergedAndroidResources of(
      ParsedAndroidResources parsed,
      Artifact mergedResources,
      Artifact classJar,
      Artifact aapt2RTxt,
      @Nullable Artifact dataBindingInfoZip,
      ResourceDependencies resourceDependencies,
      ProcessedAndroidManifest manifest) {
    return new MergedAndroidResources(
        parsed,
        mergedResources,
        classJar,
        aapt2RTxt,
        dataBindingInfoZip,
        resourceDependencies,
        manifest);
  }

  MergedAndroidResources(MergedAndroidResources other) {
    this(
        other,
        other.mergedResources,
        other.classJar,
        other.aapt2RTxt,
        other.dataBindingInfoZip,
        other.resourceDependencies,
        other.manifest);
  }

  protected MergedAndroidResources(
      ParsedAndroidResources other,
      Artifact mergedResources,
      Artifact classJar,
      Artifact aapt2RTxt,
      @Nullable Artifact dataBindingInfoZip,
      ResourceDependencies resourceDependencies,
      ProcessedAndroidManifest manifest) {
    super(other, manifest);
    this.mergedResources = mergedResources;
    this.classJar = classJar;
    this.aapt2RTxt = aapt2RTxt;
    this.dataBindingInfoZip = dataBindingInfoZip;
    this.resourceDependencies = resourceDependencies;
    this.manifest = manifest;
  }

  /**
   * Gets an Artifact containing a zip of merged resources.
   *
   * <p>If assets were processed together with resources, the zip will also contain merged assets.
   *
   * @deprecated This artifact is produced by an often-expensive action and should not be used if
   *     another option is available. Furthermore, it will be replaced by flat files once we
   *     completely move to aapt2.
   */
  @Deprecated
  public Artifact getMergedResources() {
    return mergedResources;
  }

  public Artifact getClassJar() {
    return classJar;
  }

  @Nullable
  public Artifact getDataBindingInfoZip() {
    return dataBindingInfoZip;
  }

  public Artifact getJavaClassJar() {
    return classJar;
  }

  @Nullable
  Artifact getAapt2RTxt() {
    return aapt2RTxt;
  }

  @Override
  public ProcessedAndroidManifest getStampedManifest() {
    return manifest;
  }

  public ProcessedAndroidManifest getProcessedManifest() {
    return manifest;
  }

  public ResourceDependencies getResourceDependencies() {
    return resourceDependencies;
  }

  /**
   * Validates and packages this rule's resources.
   *
   * <p>See {@link ValidatedAndroidResources#validateFrom(AndroidDataContext,
   * MergedAndroidResources)}. This method is a convenience method for calling that one.
   */
  public ValidatedAndroidResources validate(AndroidDataContext dataContext)
      throws InterruptedException {
    return ValidatedAndroidResources.validateFrom(dataContext, this, ImmutableList.of());
  }

  /**
   * Validates and packages this rule's resources.
   *
   * <p>See {@link ValidatedAndroidResources#validateFrom(AndroidDataContext,
   * MergedAndroidResources)}. This method is a convenience method for calling that one.
   */
  public ValidatedAndroidResources validate(
      AndroidDataContext dataContext, List<Artifact> resApkDeps) throws InterruptedException {
    return ValidatedAndroidResources.validateFrom(dataContext, this, resApkDeps);
  }

  @Override
  public Optional<? extends MergedAndroidResources> maybeFilter(
      RuleErrorConsumer errorConsumer, ResourceFilter resourceFilter, boolean isDependency)
      throws RuleErrorException {
    return super.maybeFilter(errorConsumer, resourceFilter, isDependency)
        .map(
            parsed ->
                MergedAndroidResources.of(
                    parsed,
                    mergedResources,
                    classJar,
                    aapt2RTxt,
                    dataBindingInfoZip,
                    resourceDependencies,
                    manifest));
  }

  @Override
  public boolean equals(Object object) {
    if (!super.equals(object) || !(object instanceof MergedAndroidResources)) {
      return false;
    }

    MergedAndroidResources other = (MergedAndroidResources) object;
    return Objects.equals(mergedResources, other.mergedResources)
        && classJar.equals(other.classJar)
        && Objects.equals(aapt2RTxt, other.aapt2RTxt)
        && Objects.equals(dataBindingInfoZip, other.dataBindingInfoZip)
        && resourceDependencies.equals(other.resourceDependencies);
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        super.hashCode(),
        mergedResources,
        classJar,
        aapt2RTxt,
        dataBindingInfoZip,
        resourceDependencies);
  }
}
