/*
 * Copyright 2013-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 com.facebook.buck.java.AccumulateClassNames;
import com.facebook.buck.java.JavaLibraryRule;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.rules.AbstractBuildRuleBuilderParams;
import com.facebook.buck.rules.AbstractBuildable;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.Buildable;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.OnDiskBuildInfo;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.CompositeStep;
import com.facebook.buck.step.ConditionalStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.FileExistsAndIsNotEmptyStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.facebook.buck.step.fs.RmStep;
import com.facebook.buck.util.BuckConstant;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

import javax.annotation.Nullable;

/**
 * {@link DexProducedFromJavaLibraryThatContainsClassFiles} is a {@link Buildable} that serves a
 * very specific purpose: it takes a {@link JavaLibraryRule} and the list of classes in the
 * {@link JavaLibraryRule} (which is represented by an {@link AccumulateClassNames}), and dexes the
 * output of the {@link JavaLibraryRule} if its list of classes is non-empty. Because it is
 * expected to be used with pre-dexing, we always pass the {@code --force-jumbo} flag to {@code dx}
 * in this buildable.
 * <p>
 * Most {@link Buildable}s can determine the (possibly null) path to their output file from their
 * definition. This is an anomaly because we do not know whether this will write a {@code .dex} file
 * until runtime. Unfortunately, because there is no such thing as an empty {@code .dex} file, we
 * cannot write a meaningful "dummy .dex" if there are no class files to pass to {@code dx}.
 */
public class DexProducedFromJavaLibraryThatContainsClassFiles extends AbstractBuildable {

  /**
   * Key used with {@link OnDiskBuildInfo} to identify whether this {@link Buildable} has
   * generated a {@code .dex} files. The only expected value to be associated with this key is
   * {@code "true"}.
   */
  private static final String HAS_DEX_OUTPUT_METADATA = "HAS_DEX_OUTPUT";

  private final BuildTarget buildTarget;
  private final AccumulateClassNames javaLibraryWithClassesList;

  /** This {@link Supplier} will be defined and determined after this buildable is built. */
  @Nullable
  private Supplier<Boolean> hasOutputFile;

  private DexProducedFromJavaLibraryThatContainsClassFiles(BuildTarget buildTarget,
      AccumulateClassNames javaLibraryWithClassesList) {
    this.buildTarget = Preconditions.checkNotNull(buildTarget);
    this.javaLibraryWithClassesList = Preconditions.checkNotNull(javaLibraryWithClassesList);
  }

  public BuildTarget getBuildTarget() {
    return buildTarget;
  }

  @Override
  public Iterable<String> getInputsToCompareToOutput() {
    // The deps of this rule already capture all of the inputs that should affect the cache key.
    return ImmutableList.of();
  }

  @Override
  public List<Step> getBuildSteps(BuildContext context, final BuildableContext buildableContext)
      throws IOException {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    steps.add(new RmStep(getPathToDex().toString(), /* shouldForceDeletion */ true));

    // Make sure that the buck-out/gen/ directory exists for this.buildTarget.
    steps.add(new MkdirStep(getPathToDex().getParent()));

    // Check whether the list of class files in the JavaLibraryRule is empty.
    FileExistsAndIsNotEmptyStep fileExistsStep = new FileExistsAndIsNotEmptyStep(
        Paths.get(javaLibraryWithClassesList.getPathToOutputFile()));
    hasOutputFile = fileExistsStep;
    steps.add(fileExistsStep);

    // To be conservative, use --force-jumbo for these intermediate .dex files so that they can be
    // merged into a final classes.dex that uses jumbo instructions.
    JavaLibraryRule javaLibraryRuleToDex = javaLibraryWithClassesList.getJavaLibraryRule();
    DxStep dx = new DxStep(getPathToDex().toString(),
        Collections.singleton(Paths.get(javaLibraryRuleToDex.getPathToOutputFile())),
        EnumSet.of(DxStep.Option.NO_OPTIMIZE, DxStep.Option.FORCE_JUMBO));
    AbstractExecutionStep recordArtifactStep = new AbstractExecutionStep("record dx success") {
      @Override
      public int execute(ExecutionContext context) {
        buildableContext.recordArtifact(getPathToDex().getFileName());
        buildableContext.addMetadata(HAS_DEX_OUTPUT_METADATA, "true");
        return 0;
      }
    };
    CompositeStep dxAndStore = new CompositeStep(ImmutableList.of(dx, recordArtifactStep));

    // Make sure that there are .class files to dex before running dx.
    ConditionalStep runDxIfThereAreClassFiles = new ConditionalStep(fileExistsStep, dxAndStore);
    steps.add(runDxIfThereAreClassFiles);

    return steps.build();
  }

  @Override
  @Nullable
  public String getPathToOutputFile() {
    // A .dex file is not guaranteed to be generated, so we return null to be conservative.
    return null;
  }

  public Path getPathToDex() {
    return Paths.get(
        BuckConstant.GEN_DIR,
        buildTarget.getBasePath(),
        buildTarget.getShortName() + ".dex.jar");
  }

  public boolean hasOutput() {
    // TODO(mbolin): Assert that this Buildable has been built. Currently, there is no way to do
    // that from a Buildable (but there is from an AbstractCachingBuildRule).
    Preconditions.checkNotNull(hasOutputFile);
    return hasOutputFile.get();
  }

  @Override
  protected void initializeFromDisk(OnDiskBuildInfo onDiskBuildInfo) {
    boolean hasOutput = "true".equals(onDiskBuildInfo.getValue(HAS_DEX_OUTPUT_METADATA).orNull());
    this.hasOutputFile = Suppliers.ofInstance(hasOutput);
  }

  public static Builder newPreDexBuilder(AbstractBuildRuleBuilderParams params) {
    return new Builder(params);
  }

  public static class Builder extends AbstractBuildable.Builder {

    private AccumulateClassNames javaLibraryWithClassesList;

    private Builder(AbstractBuildRuleBuilderParams params) {
      super(params);
    }

    @Override
    protected BuildRuleType getType() {
      return BuildRuleType._PRE_DEX;
    }

    @Override
    protected DexProducedFromJavaLibraryThatContainsClassFiles newBuildable(
        BuildRuleParams params, BuildRuleResolver resolver) {
      return new DexProducedFromJavaLibraryThatContainsClassFiles(params.getBuildTarget(),
          javaLibraryWithClassesList);
    }

    public Builder setPathToClassNamesList(AccumulateClassNames javaLibraryWithClassesList) {
      this.javaLibraryWithClassesList = javaLibraryWithClassesList;
      return this;
    }
  }
}
