/*
 * 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 com.facebook.buck.event.ThrowableLogEvent;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.CompositeStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.util.AndroidPlatformTarget;
import com.facebook.buck.zip.CustomZipOutputStream;
import com.facebook.buck.zip.ZipOutputStreams;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.io.Files;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;

public final class ProGuardObfuscateStep extends ShellStep {

  private final Map<String, String> inputAndOutputEntries;
  private final String pathToProGuardCommandLineArgsFile;

  /**
   * @return step that writes out ProGuard's command line arguments to a text file and then runs
   *     ProGuard using those arguments. We write the arguments to a file to avoid blowing out
   *     exec()'s ARG_MAX limit.
   */
  public static Step create(
      String generatedProGuardConfig,
      Set<String> customProguardConfigs,
      boolean useProguardOptimizations,
      Map<String, String> inputAndOutputEntries,
      Set<String> additionalLibraryJarsForProguard,
      String proguardDirectory) {

    String pathToProGuardCommandLineArgsFile = proguardDirectory + "/command-line.txt";

    CommandLineHelperStep commandLineHelperStep = new CommandLineHelperStep(
        generatedProGuardConfig,
        customProguardConfigs,
        useProguardOptimizations,
        inputAndOutputEntries,
        additionalLibraryJarsForProguard,
        proguardDirectory,
        pathToProGuardCommandLineArgsFile);

    ProGuardObfuscateStep proGuardStep = new ProGuardObfuscateStep(
        inputAndOutputEntries, pathToProGuardCommandLineArgsFile);

    return new CompositeStep(ImmutableList.of(commandLineHelperStep, proGuardStep));
  }

  /**
   * @param inputAndOutputEntries Map of input/output pairs to proguard. The key represents an
   *     input jar (-injars); the value an output jar (-outjars).
   * @param pathToProGuardCommandLineArgsFile Path to file containing arguments to ProGuard.
   */
  private ProGuardObfuscateStep(
      Map<String, String> inputAndOutputEntries,
      String pathToProGuardCommandLineArgsFile) {
    this.inputAndOutputEntries = ImmutableMap.copyOf(inputAndOutputEntries);
    this.pathToProGuardCommandLineArgsFile = Preconditions.checkNotNull(
        pathToProGuardCommandLineArgsFile);
  }

  @Override
  public String getShortName() {
    return "proguard_obfuscation";
  }

  @Override
  protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) {
    AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget();

    // Run ProGuard as a standalone executable JAR file.
    String proguardJar = androidPlatformTarget.getProguardJar().getAbsolutePath();

    ImmutableList.Builder<String> args = ImmutableList.builder();
    args.add("java")
        .add("-Xmx1024M")
        .add("-jar").add(proguardJar)
        .add("@" + pathToProGuardCommandLineArgsFile);
    return args.build();
  }

  @Override
  public int execute(ExecutionContext context) {
    int exitCode = super.execute(context);

    // proguard has a peculiar behaviour when multiple -injars/outjars pairs are specified in which
    // any -injars that would have been fully stripped away will not produce their matching -outjars
    // as requested (so the file won't exist).  Our build steps are not sophisticated enough to
    // account for this and remove those entries from the classes to dex so we hack things here to
    // ensure that the files exist but are empty.
    if (exitCode == 0) {
      exitCode = ensureAllOutputsExist(context);
    }

    return exitCode;
  }

  private int ensureAllOutputsExist(ExecutionContext context) {
    for (String outputJar : inputAndOutputEntries.values()) {
      File outputJarFile = new File(outputJar);
      if (!outputJarFile.exists()) {
        try {
          createEmptyZip(outputJarFile);
        } catch (IOException e) {
          context.getBuckEventBus().post(ThrowableLogEvent.create(e,
              "Error creating empty zip file at: %s.",
              outputJarFile));
          return 1;
        }
      }
    }
    return 0;
  }

  @VisibleForTesting
  static void createEmptyZip(File file) throws IOException {
    Files.createParentDirs(file);
    CustomZipOutputStream out = ZipOutputStreams.newOutputStream(file);
    // Sun's java 6 runtime doesn't allow us to create a truly empty zip, but this should be enough
    // to pass through dx/split-zip without any issue.
    // ...and Sun's java 7 runtime doesn't let us use an empty string for the zip entry name.
    out.putNextEntry(new ZipEntry("proguard_no_result"));
    out.close();
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    } else if (!(obj instanceof ProGuardObfuscateStep)) {
      return false;
    }

    ProGuardObfuscateStep that = (ProGuardObfuscateStep) obj;
    return Objects.equal(this.inputAndOutputEntries, that.inputAndOutputEntries) &&
        Objects.equal(this.pathToProGuardCommandLineArgsFile,
            that.pathToProGuardCommandLineArgsFile);
  }

  @Override
  public int hashCode() {
    return Objects.hashCode(inputAndOutputEntries, pathToProGuardCommandLineArgsFile);
  }

  /**
   * Helper class to run as a step before ProGuardObfuscateStep to write out the
   * command-line parameters to a file.  The ProGuardObfuscateStep references
   * this file when it runs using ProGuard's '@' syntax.  This allows for longer
   * command-lines than would otherwise be supported.
   */
  private static class CommandLineHelperStep extends AbstractExecutionStep {

    private final String generatedProGuardConfig;
    private final Set<String> customProguardConfigs;
    private final Map<String, String> inputAndOutputEntries;
    private final Set<String> additionalLibraryJarsForProguard;
    private final boolean useAndroidProguardConfigWithOptimizations;
    private final String proguardDirectory;
    private final String pathToProGuardCommandLineArgsFile;

    /**
     * @param generatedProGuardConfig Proguard configuration as produced by aapt.
     * @param customProguardConfigs Main rule and its dependencies proguard configurations.
     * @param useProguardOptimizations Whether to include the Android SDK proguard defaults.
     * @param inputAndOutputEntries Map of input/output pairs to proguard.  The key represents an
     *     input jar (-injars); the value an output jar (-outjars).
     * @param additionalLibraryJarsForProguard Libraries that are not operated upon by proguard but
     *     needed to resolve symbols.
     * @param proguardDirectory Output directory for various proguard-generated meta artifacts.
     * @param pathToProGuardCommandLineArgsFile Path to file containing arguments to ProGuard.
     */
    private CommandLineHelperStep(
        String generatedProGuardConfig,
        Set<String> customProguardConfigs,
        boolean useProguardOptimizations,
        Map<String, String> inputAndOutputEntries,
        Set<String> additionalLibraryJarsForProguard,
        String proguardDirectory,
        String pathToProGuardCommandLineArgsFile) {
      super("write_proguard_command_line_parameters");
      this.generatedProGuardConfig = Preconditions.checkNotNull(generatedProGuardConfig);
      this.customProguardConfigs = ImmutableSet.copyOf(customProguardConfigs);
      this.useAndroidProguardConfigWithOptimizations = useProguardOptimizations;
      this.inputAndOutputEntries = ImmutableMap.copyOf(inputAndOutputEntries);
      this.additionalLibraryJarsForProguard = ImmutableSet.copyOf(additionalLibraryJarsForProguard);
      this.proguardDirectory = Preconditions.checkNotNull(proguardDirectory);
      this.pathToProGuardCommandLineArgsFile = pathToProGuardCommandLineArgsFile;
    }

    @Override
    public int execute(ExecutionContext context) {
      String proGuardArguments = Joiner.on('\n').join(getParameters(context));
      try {
        context.getProjectFilesystem().writeContentsToPath(
            proGuardArguments,
            Paths.get(pathToProGuardCommandLineArgsFile));
      } catch (IOException e) {
        context.getBuckEventBus().post(ThrowableLogEvent.create(e,
            "Error writing ProGuard arguments to file: %s.",
            pathToProGuardCommandLineArgsFile));
        return 1;
      }

      return 0;
    }

    /** @return the list of arguments to pass to ProGuard. */
    private ImmutableList<String> getParameters(ExecutionContext context) {
      ImmutableList.Builder<String> args = ImmutableList.builder();
      AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget();
      Joiner pathJoiner = Joiner.on(':');

      // Relative paths should be interpreted relative to project directory root, not the
      // written parameters file.
      args.add("-basedirectory")
          .add(context.getProjectDirectoryRoot().getAbsolutePath());

      // -include
      if (useAndroidProguardConfigWithOptimizations) {
        args.add("-include")
            .add(androidPlatformTarget.getOptimizedProguardConfig().getAbsolutePath());
      } else {
        args.add("-include").add(androidPlatformTarget.getProguardConfig().getAbsolutePath());
      }
      for (String proguardConfig : customProguardConfigs) {
        args.add("-include").add(proguardConfig);
      }
      args.add("-include").add(generatedProGuardConfig);

      // -injars and -outjars paired together for each input.
      for (Map.Entry<String, String> inputOutputEntry : inputAndOutputEntries.entrySet()) {
        args.add("-injars").add(inputOutputEntry.getKey());
        args.add("-outjars").add(inputOutputEntry.getValue());
      }

      // -libraryjars
      Iterable<String> bootclasspathPaths = Iterables.transform(
          androidPlatformTarget.getBootclasspathEntries(),
          Functions.toStringFunction());
      Iterable<String> libraryJars = Iterables.concat(bootclasspathPaths,
          additionalLibraryJarsForProguard);
      args.add("-libraryjars").add(pathJoiner.join(libraryJars));

      // -dump
      args.add("-dump").add(proguardDirectory + "/dump.txt");
      args.add("-printseeds").add(proguardDirectory + "/seeds.txt");
      args.add("-printusage").add(proguardDirectory + "/usage.txt");
      args.add("-printmapping").add(proguardDirectory + "/mapping.txt");
      args.add("-printconfiguration").add(proguardDirectory + "/configuration.txt");

      return args.build();
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof CommandLineHelperStep)) {
        return false;
      }
      CommandLineHelperStep that = (CommandLineHelperStep) obj;

      return
          Objects.equal(useAndroidProguardConfigWithOptimizations,
              that.useAndroidProguardConfigWithOptimizations) &&
          Objects.equal(additionalLibraryJarsForProguard,
              that.additionalLibraryJarsForProguard) &&
          Objects.equal(customProguardConfigs, that.customProguardConfigs) &&
          Objects.equal(generatedProGuardConfig, that.generatedProGuardConfig) &&
          Objects.equal(inputAndOutputEntries, that.inputAndOutputEntries) &&
          Objects.equal(proguardDirectory, that.proguardDirectory) &&
          Objects.equal(pathToProGuardCommandLineArgsFile, that.pathToProGuardCommandLineArgsFile);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(useAndroidProguardConfigWithOptimizations,
          additionalLibraryJarsForProguard,
          customProguardConfigs,
          generatedProGuardConfig,
          inputAndOutputEntries,
          proguardDirectory,
          pathToProGuardCommandLineArgsFile);
    }
  }
}
