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

import android.databinding.AndroidDataBinding;
import android.databinding.cli.ProcessXmlOptions;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.core.VariantConfiguration;
import com.android.builder.core.VariantType;
import com.android.builder.dependency.SymbolFileProvider;
import com.android.builder.model.AaptOptions;
import com.android.ide.common.internal.CommandLineRunner;
import com.android.ide.common.internal.ExecutorSingleton;
import com.android.ide.common.internal.LoggedErrorException;
import com.android.repository.Revision;
import com.android.utils.ILogger;
import com.android.utils.StdLogger;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.RevisionConverter;
import com.google.devtools.build.android.junctions.JunctionCreator;
import com.google.devtools.build.android.junctions.NoopJunctionCreator;
import com.google.devtools.build.android.junctions.WindowsJunctionCreator;
import com.google.devtools.build.android.resources.ResourceSymbols;
import com.google.devtools.common.options.Converters.CommaSeparatedOptionListConverter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
import com.google.devtools.common.options.OptionEffectTag;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.TriState;
import java.io.Closeable;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/** Provides a wrapper around the AOSP build tools for resource processing. */
public class AndroidResourceProcessor {
  static final Logger logger = Logger.getLogger(AndroidResourceProcessor.class.getName());

  /** Options class containing flags for Aapt setup. */
  public static final class AaptConfigOptions extends OptionsBase {
    @Option(
      name = "buildToolsVersion",
      defaultValue = "null",
      converter = RevisionConverter.class,
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Version of the build tools (e.g. aapt) being used, e.g. 23.0.2"
    )
    public Revision buildToolsVersion;

    @Option(
      name = "aapt",
      defaultValue = "null",
      converter = ExistingPathConverter.class,
      category = "tool",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Aapt tool location for resource packaging."
    )
    public Path aapt;

    @Option(
      name = "androidJar",
      defaultValue = "null",
      converter = ExistingPathConverter.class,
      category = "tool",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Path to the android jar for resource packaging and building apks."
    )
    public Path androidJar;

    @Option(
      name = "useAaptCruncher",
      defaultValue = "auto",
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "Use the legacy aapt cruncher, defaults to true for non-LIBRARY packageTypes. "
              + " LIBRARY packages do not benefit from the additional processing as the resources"
              + " will need to be reprocessed during the generation of the final apk. See"
              + " https://code.google.com/p/android/issues/detail?id=67525 for a discussion of the"
              + " different png crunching methods."
    )
    public TriState useAaptCruncher;

    @Option(
      name = "uncompressedExtensions",
      defaultValue = "",
      converter = CommaSeparatedOptionListConverter.class,
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "A list of file extensions not to compress."
    )
    public List<String> uncompressedExtensions;

    @Option(
      name = "debug",
      defaultValue = "false",
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Indicates if it is a debug build."
    )
    public boolean debug;

    @Option(
      name = "resourceConfigs",
      defaultValue = "",
      converter = CommaSeparatedOptionListConverter.class,
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "A list of resource config filters to pass to aapt."
    )
    public List<String> resourceConfigs;
  }

  /** {@link AaptOptions} backed by an {@link AaptConfigOptions}. */
  public static final class FlagAaptOptions implements AaptOptions {
    private final AaptConfigOptions options;

    public FlagAaptOptions(AaptConfigOptions options) {
      this.options = options;
    }

    @Override
    public Collection<String> getNoCompress() {
      if (!options.uncompressedExtensions.isEmpty()) {
        return options.uncompressedExtensions;
      }
      return ImmutableList.of();
    }

    @Override
    public String getIgnoreAssets() {
      return null;
    }

    @Override
    public boolean getFailOnMissingConfigEntry() {
      return false;
    }

    @Override
    public List<String> getAdditionalParameters() {
      return ImmutableList.of();
    }
  }

  private final StdLogger stdLogger;

  public AndroidResourceProcessor(StdLogger stdLogger) {
    this.stdLogger = stdLogger;
  }

  // TODO(bazel-team): Clean up this method call -- 13 params is too many.
  /**
   * Processes resources for generated sources, configs and packaging resources.
   *
   * <p>Returns a post-processed MergedAndroidData. Notably, the resources will be stripped of any
   * databinding expressions.
   */
  public MergedAndroidData processResources(
      Path tempRoot,
      Path aapt,
      Path androidJar,
      @Nullable Revision buildToolsVersion,
      VariantType variantType,
      boolean debug,
      String customPackageForR,
      AaptOptions aaptOptions,
      Collection<String> resourceConfigs,
      MergedAndroidData primaryData,
      List<DependencyAndroidData> dependencyData,
      @Nullable Path sourceOut,
      @Nullable Path packageOut,
      @Nullable Path proguardOut,
      @Nullable Path mainDexProguardOut,
      @Nullable Path publicResourcesOut,
      @Nullable Path dataBindingInfoOut)
      throws IOException, InterruptedException, LoggedErrorException {
    Path androidManifest = primaryData.getManifest();
    final Path resourceDir =
        processDataBindings(
            primaryData.getResourceDir().resolveSibling("res_no_binding"),
            primaryData.getResourceDir(),
            dataBindingInfoOut,
            customPackageForR,
            /* shouldZipDataBindingInfo= */ true);

    final Path assetsDir = primaryData.getAssetDir();
    if (publicResourcesOut != null) {
      prepareOutputPath(publicResourcesOut.getParent());
    }
    runAapt(
        tempRoot,
        aapt,
        androidJar,
        buildToolsVersion,
        variantType,
        debug,
        customPackageForR,
        aaptOptions,
        resourceConfigs,
        androidManifest,
        resourceDir,
        assetsDir,
        sourceOut,
        packageOut,
        proguardOut,
        mainDexProguardOut,
        publicResourcesOut);
    // The R needs to be created for each library in the dependencies,
    // but only if the current project is not a library.
    if (sourceOut != null && variantType != VariantType.LIBRARY) {
      writeDependencyPackageRJavaFiles(
          dependencyData, customPackageForR, androidManifest, sourceOut);
    }
    return new MergedAndroidData(resourceDir, assetsDir, androidManifest);
  }

  public void runAapt(
      Path tempRoot,
      Path aapt,
      Path androidJar,
      @Nullable Revision buildToolsVersion,
      VariantType variantType,
      boolean debug,
      String customPackageForR,
      AaptOptions aaptOptions,
      Collection<String> resourceConfigs,
      Path androidManifest,
      Path resourceDir,
      Path assetsDir,
      Path sourceOut,
      @Nullable Path packageOut,
      @Nullable Path proguardOut,
      @Nullable Path mainDexProguardOut,
      @Nullable Path publicResourcesOut)
      throws InterruptedException, LoggedErrorException, IOException {
    try (JunctionCreator junctions =
        System.getProperty("os.name").toLowerCase().startsWith("windows")
            ? new WindowsJunctionCreator(Files.createDirectories(tempRoot.resolve("juncts")))
            : new NoopJunctionCreator()) {
      sourceOut = junctions.create(sourceOut);
      AaptCommandBuilder commandBuilder =
          new AaptCommandBuilder(junctions.create(aapt))
              .forBuildToolsVersion(buildToolsVersion)
              .forVariantType(variantType)
              // first argument is the command to be executed, "package"
              .add("package")
              // If the logger is verbose, set aapt to be verbose
              .when(stdLogger.getLevel() == StdLogger.Level.VERBOSE)
              .thenAdd("-v")
              // Overwrite existing files, if they exist.
              .add("-f")
              // Resources are precrunched in the merge process.
              .add("--no-crunch")
              // Do not automatically generate versioned copies of vector XML resources.
              .whenVersionIsAtLeast(new Revision(23))
              .thenAdd("--no-version-vectors")
              // Add the android.jar as a base input.
              .add("-I", junctions.create(androidJar))
              // Add the manifest for validation.
              .add("-M", junctions.create(androidManifest.toAbsolutePath()))
              // Maybe add the resources if they exist
              .when(Files.isDirectory(resourceDir))
              .thenAdd("-S", junctions.create(resourceDir))
              // Maybe add the assets if they exist
              .when(Files.isDirectory(assetsDir))
              .thenAdd("-A", junctions.create(assetsDir))
              // Outputs
              .when(sourceOut != null)
              .thenAdd("-m")
              .add("-J", prepareOutputPath(sourceOut))
              .add("--output-text-symbols", prepareOutputPath(sourceOut))
              .add("-F", junctions.create(packageOut))
              .add("-G", junctions.create(proguardOut))
              .whenVersionIsAtLeast(new Revision(24))
              .thenAdd("-D", junctions.create(mainDexProguardOut))
              .add("-P", junctions.create(publicResourcesOut))
              .when(debug)
              .thenAdd("--debug-mode")
              .add("--custom-package", customPackageForR)
              // If it is a library, do not generate final java ids.
              .whenVariantIs(VariantType.LIBRARY)
              .thenAdd("--non-constant-id")
              .add("--ignore-assets", aaptOptions.getIgnoreAssets())
              .when(aaptOptions.getFailOnMissingConfigEntry())
              .thenAdd("--error-on-missing-config-entry")
              // Never compress apks.
              .add("-0", "apk")
              // Add custom no-compress extensions.
              .addRepeated("-0", aaptOptions.getNoCompress())
              // Filter by resource configuration type.
              .add("-c", Joiner.on(',').join(resourceConfigs));
      for (String additional : aaptOptions.getAdditionalParameters()) {
        commandBuilder.add(additional);
      }
      try {
        new CommandLineRunner(stdLogger).runCmdLine(commandBuilder.build(), null);
      } catch (LoggedErrorException e) {
        // Add context and throw the error to resume processing.
        throw new LoggedErrorException(
            e.getCmdLineError(), getOutputWithSourceContext(aapt, e.getOutput()), e.getCmdLine());
      }
    }
  }

  /** Adds 10 lines of source to each syntax error. Very useful for debugging. */
  private List<String> getOutputWithSourceContext(Path aapt, List<String> lines)
      throws IOException {
    List<String> outputWithSourceContext = new ArrayList<>();
    for (String line : lines) {
      if (line.contains("Duplicate file") || line.contains("Original")) {
        String[] parts = line.split(":");
        String fileName = parts[0].trim();
        outputWithSourceContext.add("\n" + fileName + ":\n\t");
        outputWithSourceContext.add(
            Joiner.on("\n\t")
                .join(
                    Files.readAllLines(
                        aapt.getFileSystem().getPath(fileName), StandardCharsets.UTF_8)));
      } else if (line.contains("error")) {
        String[] parts = line.split(":");
        String fileName = parts[0].trim();
        try {
          int lineNumber = Integer.valueOf(parts[1].trim());
          StringBuilder expandedError =
              new StringBuilder("\nError at " + lineNumber + " : " + line);
          List<String> errorSource =
              Files.readAllLines(aapt.getFileSystem().getPath(fileName), StandardCharsets.UTF_8);
          for (int i = Math.max(lineNumber - 5, 0);
              i < Math.min(lineNumber + 5, errorSource.size());
              i++) {
            expandedError.append("\n").append(i).append("\t:  ").append(errorSource.get(i));
          }
          outputWithSourceContext.add(expandedError.toString());
        } catch (IOException | NumberFormatException formatError) {
          outputWithSourceContext.add("error parsing line" + line);
          stdLogger.error(formatError, "error during reading source %s", fileName);
        }
      } else {
        outputWithSourceContext.add(line);
      }
    }
    return outputWithSourceContext;
  }

  /**
   * If resources exist and a data binding layout info file is requested: processes data binding
   * declarations over those resources, populates the output file, and creates a new resources
   * directory with data binding expressions stripped out (so aapt, which doesn't understand data
   * binding, can properly read them).
   *
   * <p>Returns the resources directory that aapt should read.
   */
  static Path processDataBindings(
      Path processedResourceOutputDirectory,
      Path inputResourcesDir,
      Path dataBindingInfoOut,
      String packagePath,
      boolean shouldZipDataBindingInfo)
      throws IOException {

    if (dataBindingInfoOut == null) {
      return inputResourcesDir;
    } else if (!Files.isDirectory(inputResourcesDir)) {
      // No resources: no data binding needed. Create a dummy file to satisfy declared outputs.
      Files.createFile(dataBindingInfoOut);
      return inputResourcesDir;
    }

    // Strip the file name (the data binding library automatically adds it back in).
    // ** The data binding library assumes this file is called "layout-info.zip". **
    if (shouldZipDataBindingInfo) {
      dataBindingInfoOut = dataBindingInfoOut.getParent();
      if (Files.notExists(dataBindingInfoOut)) {
        Files.createDirectory(dataBindingInfoOut);
      }
    }

    // Create a directory for the resources, namespaced with the old resource path
    Path processedResourceDir =
        Files.createDirectories(
            processedResourceOutputDirectory.resolve(
                inputResourcesDir.isAbsolute()
                    ? inputResourcesDir.getRoot().relativize(inputResourcesDir)
                    : inputResourcesDir));

    ProcessXmlOptions options = new ProcessXmlOptions();
    options.setAppId(packagePath);
    options.setResInput(inputResourcesDir.toFile());
    options.setResOutput(processedResourceDir.toFile());
    options.setLayoutInfoOutput(dataBindingInfoOut.toFile());
    // Whether or not to aggregate data-bound .xml files into a single .zip.
    options.setZipLayoutInfo(shouldZipDataBindingInfo);

    try {
      AndroidDataBinding.doRun(options);
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
    return processedResourceDir;
  }

  public ResourceSymbols loadResourceSymbolTable(
      Iterable<? extends SymbolFileProvider> libraries,
      String appPackageName,
      Path primaryRTxt,
      Multimap<String, ResourceSymbols> libMap)
      throws IOException {
    // The reported availableProcessors may be higher than the actual resources
    // (on a shared system). On the other hand, a lot of the work is I/O, so it's not completely
    // CPU bound. As a compromise, divide by 2 the reported availableProcessors.
    int numThreads = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);
    ListeningExecutorService executorService =
        MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(numThreads));
    try (Closeable closeable = ExecutorServiceCloser.createWith(executorService)) {
      for (Map.Entry<String, ListenableFuture<ResourceSymbols>> entry :
          ResourceSymbols.loadFrom(libraries, executorService, appPackageName).entries()) {
        libMap.put(entry.getKey(), entry.getValue().get());
      }
      if (primaryRTxt != null && Files.exists(primaryRTxt)) {
        return ResourceSymbols.load(primaryRTxt, executorService).get();
      }
      return ResourceSymbols.merge(libMap.values());
    } catch (InterruptedException | ExecutionException e) {
      throw new IOException("Failed to load SymbolFile: ", e);
    }
  }

  void writeDependencyPackageRJavaFiles(
      List<DependencyAndroidData> dependencyData,
      String customPackageForR,
      Path androidManifest,
      Path sourceOut)
      throws IOException {
    List<SymbolFileProvider> libraries = new ArrayList<>();
    for (DependencyAndroidData dataDep : dependencyData) {
      SymbolFileProvider library = dataDep.asSymbolFileProvider();
      libraries.add(library);
    }
    String appPackageName = customPackageForR;
    if (appPackageName == null) {
      appPackageName = VariantConfiguration.getManifestPackage(androidManifest.toFile());
    }
    Multimap<String, ResourceSymbols> libSymbolMap = ArrayListMultimap.create();
    Path primaryRTxt = sourceOut != null ? sourceOut.resolve("R.txt") : null;
    if (primaryRTxt != null && !libraries.isEmpty()) {
      ResourceSymbols fullSymbolValues =
          loadResourceSymbolTable(libraries, appPackageName, primaryRTxt, libSymbolMap);
      // Loop on all the package name, merge all the symbols to write, and write.
      for (String packageName : libSymbolMap.keySet()) {
        Collection<ResourceSymbols> symbols = libSymbolMap.get(packageName);
        fullSymbolValues.writeSourcesTo(sourceOut, packageName, symbols, /* finalFields= */ true);
      }
    }
  }

  /** A logger that will print messages to a target OutputStream. */
  static final class PrintStreamLogger implements ILogger {
    private final PrintStream out;

    public PrintStreamLogger(PrintStream stream) {
      this.out = stream;
    }

    @Override
    public void error(@Nullable Throwable t, @Nullable String msgFormat, Object... args) {
      if (msgFormat != null) {
        out.println(String.format("Error: " + msgFormat, args));
      }
      if (t != null) {
        out.printf("Error: %s%n", t.getMessage());
      }
    }

    @Override
    public void warning(@NonNull String msgFormat, Object... args) {
      out.println(String.format("Warning: " + msgFormat, args));
    }

    @Override
    public void info(@NonNull String msgFormat, Object... args) {
      out.println(String.format("Info: " + msgFormat, args));
    }

    @Override
    public void verbose(@NonNull String msgFormat, Object... args) {
      out.println(String.format(msgFormat, args));
    }
  }

  /** Shutdown AOSP utilized thread-pool. */
  public void shutdown() {
    FullyQualifiedName.logCacheUsage(logger);
    // AOSP code never shuts down its singleton executor and leaves the process hanging.
    ExecutorSingleton.getExecutor().shutdownNow();
  }

  @Nullable
  private Path prepareOutputPath(@Nullable Path out) throws IOException {
    if (out == null) {
      return null;
    }
    return Files.createDirectories(out);
  }
}
