/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.android;

import static com.facebook.buck.rules.BuildableProperties.Kind.ANDROID;
import static com.facebook.buck.rules.BuildableProperties.Kind.LIBRARY;

import com.facebook.buck.android.aapt.MiniAapt;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.rules.AbiRule;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildOutputInitializer;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.BuildableProperties;
import com.facebook.buck.rules.InitializableFromDisk;
import com.facebook.buck.rules.OnDiskBuildInfo;
import com.facebook.buck.rules.RecordFileSha1Step;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.Sha1HashCode;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.Nullable;

/**
 * An object that represents the resources of an android library.
 * <p>
 * Suppose this were a rule defined in <code>src/com/facebook/feed/BUILD</code>:
 * <pre>
 * android_resources(
 *   name = 'res',
 *   res = 'res',
 *   assets = 'buck-assets',
 *   deps = [
 *     '//first-party/orca/lib-ui:lib-ui',
 *   ],
 * )
 * </pre>
 */
public class AndroidResource extends AbstractBuildRule
    implements AbiRule, HasAndroidResourceDeps, InitializableFromDisk<AndroidResource.BuildOutput>,
    AndroidPackageable {

  private static final BuildableProperties PROPERTIES = new BuildableProperties(ANDROID, LIBRARY);

  @VisibleForTesting
  static final String METADATA_KEY_FOR_ABI = "ANDROID_RESOURCE_ABI_KEY";

  @VisibleForTesting
  static final String METADATA_KEY_FOR_R_DOT_JAVA_PACKAGE = "METADATA_KEY_FOR_R_DOT_JAVA_PACKAGE";

  @Nullable
  private final Path res;

  /** contents of {@code res} under version control (i.e., not generated by another rule). */
  private final ImmutableSortedSet<Path> resSrcs;

  @Nullable
  private final Path assets;

  /** contents of {@code assets} under version control (i.e., not generated by another rule). */
  private final ImmutableSortedSet<Path> assetsSrcs;

  @Nullable
  private final Path pathToTextSymbolsDir;

  @Nullable
  private final Path pathToTextSymbolsFile;

  @Nullable
  private final SourcePath manifestFile;

  private final boolean hasWhitelistedStrings;

  private final ImmutableSortedSet<BuildRule> deps;

  private final BuildOutputInitializer<BuildOutput> buildOutputInitializer;

  /**
   * This is the original {@code package} argument passed to this rule.
   */
  @Nullable
  private final String rDotJavaPackageArgument;

  /**
   * Supplier that returns the package for the Java class generated for the resources in
   * {@link #res}, if any. The value for this supplier is determined, as follows:
   * <ul>
   *   <li>If the user specified a {@code package} argument, the supplier will return that value.
   *   <li>Failing that, when the rule is built, it will parse the package from the file specified
   *       by the {@code manifest} so that it can be returned by this supplier. (Note this also
   *       needs to work correctly if the rule is initialized from disk.)
   *   <li>In all other cases (e.g., both {@code package} and {@code manifest} are unspecified), the
   *       behavior is undefined.
   * </ul>
   */
  private final Supplier<String> rDotJavaPackageSupplier;

  private final AtomicReference<String> rDotJavaPackage;

  protected AndroidResource(
      BuildRuleParams buildRuleParams,
      SourcePathResolver resolver,
      final ImmutableSortedSet<BuildRule> deps,
      @Nullable final Path res,
      ImmutableSortedSet<Path> resSrcs,
      @Nullable String rDotJavaPackageArgument,
      @Nullable Path assets,
      ImmutableSortedSet<Path> assetsSrcs,
      @Nullable SourcePath manifestFile,
      boolean hasWhitelistedStrings) {
    super(buildRuleParams, resolver);
    if (res != null && rDotJavaPackageArgument == null && manifestFile == null) {
      throw new HumanReadableException(
          "When the 'res' is specified for android_resource() %s, at least one of 'package' or " +
              "'manifest' must be specified.",
          getBuildTarget());
    }

    this.res = res;
    this.resSrcs = resSrcs;
    this.assets = assets;
    this.assetsSrcs = assetsSrcs;
    this.manifestFile = manifestFile;
    this.hasWhitelistedStrings = hasWhitelistedStrings;

    BuildTarget buildTarget = buildRuleParams.getBuildTarget();
    if (res == null) {
      pathToTextSymbolsDir = null;
      pathToTextSymbolsFile = null;
    } else {
      pathToTextSymbolsDir = BuildTargets.getGenPath(buildTarget, "__%s_text_symbols__");
      pathToTextSymbolsFile = pathToTextSymbolsDir.resolve("R.txt");
    }

    this.deps = deps;

    this.buildOutputInitializer = new BuildOutputInitializer<>(buildTarget, this);

    this.rDotJavaPackageArgument = rDotJavaPackageArgument;
    this.rDotJavaPackage = new AtomicReference<>();
    if (rDotJavaPackageArgument != null) {
      this.rDotJavaPackage.set(rDotJavaPackageArgument);
    }

    this.rDotJavaPackageSupplier = new Supplier<String>() {
      @Override
      public String get() {
        String rDotJavaPackage = AndroidResource.this.rDotJavaPackage.get();
        if (rDotJavaPackage != null) {
          return rDotJavaPackage;
        } else {
          throw new RuntimeException(String.format(
              "rDotJavaPackage for %s was requested before it was made available.",
              AndroidResource.this.getBuildTarget()));
        }
      }
    };

  }

  @Override
  public ImmutableCollection<Path> getInputsToCompareToOutput() {
    ImmutableSortedSet.Builder<Path> inputs = ImmutableSortedSet.naturalOrder();

    // This should include the res/ and assets/ folders.
    inputs.addAll(resSrcs);
    inputs.addAll(assetsSrcs);

    // manifest file is optional.
    if (manifestFile != null) {
      inputs.addAll(
          getResolver().filterInputsToCompareToOutput(Collections.singleton(manifestFile)));
    }

    return inputs.build();
  }

  @Override
  @Nullable
  public Path getRes() {
    return res;
  }

  @Override
  @Nullable
  public Path getAssets() {
    return assets;
  }

  @Nullable
  public SourcePath getManifestFile() {
    return manifestFile;
  }

  @Override
  public ImmutableList<Step> getBuildSteps(
      BuildContext context,
      final BuildableContext buildableContext) {
    // If there is no res directory, then there is no R.java to generate.
    // TODO(mbolin): Change android_resources() so that 'res' is required.
    if (getRes() == null) {
      // Normally, the ABI key of a resource rule is a hash of the R.txt file that it creates.
      // That R.txt essentially combines all the R.txt files generated by transitive dependencies of
      // this rule. So, in this case (when we don't have the R.txt), the right ABI key is the
      // ABI key for deps.
      buildableContext.addMetadata(METADATA_KEY_FOR_ABI, getAbiKeyForDeps().getHash());
      return ImmutableList.of();
    }

    ImmutableList.Builder<Step> steps = ImmutableList.builder();
    steps.add(new MakeCleanDirectoryStep(pathToTextSymbolsDir));

    // If the 'package' was not specified for this android_resource(), then attempt to parse it
    // from the AndroidManifest.xml.
    if (rDotJavaPackageArgument == null) {
      steps.add(new AbstractExecutionStep("extract_android_package") {
        @Override
        public int execute(ExecutionContext context) {
          Preconditions.checkNotNull(
              manifestFile,
              "manifestFile cannot be null when res is non-null and rDotJavaPackageArgument is " +
                  "null. This should already be enforced by the constructor.");

          AndroidManifestReader androidManifestReader;
          try {
            androidManifestReader = DefaultAndroidManifestReader.forPath(
                getResolver().getPath(manifestFile),
                context.getProjectFilesystem());
          } catch (IOException e) {
            context.logError(e, "Failed to create AndroidManifestReader for %s.", manifestFile);
            return 1;
          }

          String rDotJavaPackageFromAndroidManifest = androidManifestReader.getPackage();

          AndroidResource.this.rDotJavaPackage.set(rDotJavaPackageFromAndroidManifest);
          buildableContext.addMetadata(
              METADATA_KEY_FOR_R_DOT_JAVA_PACKAGE,
              rDotJavaPackageFromAndroidManifest);
          return 0;
        }
      });
    }

    ImmutableSet<Path> pathsToSymbolsOfDeps = FluentIterable.from(getNonEmptyResourceDeps())
        .transform(GET_RES_SYMBOLS_TXT)
        .toSet();

    steps.add(new MiniAapt(res, pathToTextSymbolsFile, pathsToSymbolsOfDeps));

    buildableContext.recordArtifact(pathToTextSymbolsFile);

    steps.add(new RecordFileSha1Step(
        pathToTextSymbolsFile,
        METADATA_KEY_FOR_ABI,
        buildableContext));

    return steps.build();
  }

  @Override
  public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) {
    return builder
        .setReflectively("rDotJavaPackage", rDotJavaPackageArgument)
        .setReflectively("hasWhitelistedStrings", hasWhitelistedStrings);
  }

  @Override
  @Nullable
  public Path getPathToOutputFile() {
    return Optional.fromNullable(pathToTextSymbolsFile).orNull();
  }

  @Override
  @Nullable
  public Path getPathToTextSymbolsFile() {
    return pathToTextSymbolsFile;
  }

  @Override
  public Sha1HashCode getTextSymbolsAbiKey() {
    return buildOutputInitializer.getBuildOutput().textSymbolsAbiKey;
  }

  @Override
  public String getRDotJavaPackage() {
    String rDotJavaPackage = rDotJavaPackageSupplier.get();
    if (rDotJavaPackage == null) {
      throw new RuntimeException("No package for " + getBuildTarget());
    }
    return rDotJavaPackage;
  }

  @Override
  public BuildableProperties getProperties() {
    return PROPERTIES;
  }

  @Override
  public Sha1HashCode getAbiKeyForDeps() {
    return HasAndroidResourceDeps.ABI_HASHER.apply(
        FluentIterable.from(getNonEmptyResourceDeps())
            .toSortedSet(HasBuildTarget.BUILD_TARGET_COMPARATOR));
  }

  private Iterable<HasAndroidResourceDeps> getNonEmptyResourceDeps() {
    return FluentIterable.from(getDeps())
        .filter(HasAndroidResourceDeps.class)
        .filter(NON_EMPTY_RESOURCE);
  }

  @Override
  public BuildOutput initializeFromDisk(OnDiskBuildInfo onDiskBuildInfo) {
    Sha1HashCode sha1HashCode = onDiskBuildInfo.getHash(METADATA_KEY_FOR_ABI).get();
    Optional<String> rDotJavaPackageFromAndroidManifest = onDiskBuildInfo.getValue(
        METADATA_KEY_FOR_R_DOT_JAVA_PACKAGE);
    if (rDotJavaPackageFromAndroidManifest.isPresent()) {
      rDotJavaPackage.set(rDotJavaPackageFromAndroidManifest.get());
    }
    return new BuildOutput(sha1HashCode);
  }

  @Override
  public BuildOutputInitializer<BuildOutput> getBuildOutputInitializer() {
    return buildOutputInitializer;
  }

  @Override
  public Iterable<AndroidPackageable> getRequiredPackageables() {
    return AndroidPackageableCollector.getPackageableRules(deps);
  }

  @Override
  public void addToCollector(AndroidPackageableCollector collector) {
    if (res != null) {
      if (hasWhitelistedStrings) {
        collector.addStringWhitelistedResourceDirectory(getBuildTarget(), res);
      } else {
        collector.addResourceDirectory(getBuildTarget(), res);
      }
    }
    if (assets != null) {
      collector.addAssetsDirectory(getBuildTarget(), assets);
    }
    if (manifestFile != null) {
      collector.addManifestFile(getBuildTarget(), getResolver().getPath(manifestFile));
    }
  }

  public static class BuildOutput {
    private final Sha1HashCode textSymbolsAbiKey;

    public BuildOutput(Sha1HashCode textSymbolsAbiKey) {
      this.textSymbolsAbiKey = textSymbolsAbiKey;
    }
  }
}
