// 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 static java.nio.charset.StandardCharsets.UTF_8;

import com.android.builder.core.VariantType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.devtools.build.android.AndroidDataMerger.MergeConflictException;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.PathConverter;
import com.google.devtools.build.android.Converters.UnvalidatedAndroidDataConverter;
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.OptionsParser;
import com.google.devtools.common.options.ShellQuotedParamsFilePreProcessor;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Action to generate an AAR archive for an Android library.
 *
 * <p>
 *
 * <pre>
 * Example Usage:
 *   java/com/google/build/android/AarGeneratorAction\
 *      --mainData path/to/resources:path/to/assets:path/to/manifest\
 *      --manifest path/to/manifest\
 *      --rtxt path/to/rtxt\
 *      --classes path/to/classes.jar\
 *      --aarOutput path/to/write/archive.aar
 * </pre>
 */
public class AarGeneratorAction {
  public static final Instant DEFAULT_TIMESTAMP =
      LocalDateTime.of(2010, 1, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant();

  private static final Logger logger = Logger.getLogger(AarGeneratorAction.class.getName());

  /** Flag specifications for this action. */
  public static final class AarGeneratorOptions extends OptionsBase {
    @Option(
      name = "mainData",
      defaultValue = "null",
      converter = UnvalidatedAndroidDataConverter.class,
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help =
          "The directory containing the primary resource directory."
              + "The contents will override the contents of any other resource directories during "
              + "merging. The expected format is resources[#resources]:assets[#assets]:manifest"
    )
    public UnvalidatedAndroidData mainData;

    @Option(
      name = "manifest",
      defaultValue = "null",
      converter = ExistingPathConverter.class,
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Path to AndroidManifest.xml."
    )
    public Path manifest;

    @Option(
      name = "rtxt",
      defaultValue = "null",
      converter = ExistingPathConverter.class,
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Path to R.txt."
    )
    public Path rtxt;

    @Option(
      name = "classes",
      defaultValue = "null",
      converter = ExistingPathConverter.class,
      category = "input",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Path to classes.jar."
    )
    public Path classes;

    @Option(
        name = "proguardSpec",
        defaultValue = "null",
        converter = ExistingPathConverter.class,
        allowMultiple = true,
        category = "input",
        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
        effectTags = {OptionEffectTag.UNKNOWN},
        help = "Path to proguard spec file.")
    public List<Path> proguardSpecs;

    @Option(
      name = "aarOutput",
      defaultValue = "null",
      converter = PathConverter.class,
      category = "output",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "Path to write the archive."
    )
    public Path aarOutput;

    @Option(
      name = "throwOnResourceConflict",
      defaultValue = "false",
      category = "config",
      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
      effectTags = {OptionEffectTag.UNKNOWN},
      help = "If passed, resource merge conflicts will be treated as errors instead of warnings"
    )
    public boolean throwOnResourceConflict;
  }

  public static void main(String[] args) throws IOException {
    Stopwatch timer = Stopwatch.createStarted();
    OptionsParser optionsParser =
        OptionsParser.builder()
            .optionsClasses(AarGeneratorOptions.class, ResourceProcessorCommonOptions.class)
            .argsPreProcessor(new ShellQuotedParamsFilePreProcessor(FileSystems.getDefault()))
            .build();
    optionsParser.parseAndExitUponError(args);
    AarGeneratorOptions options = optionsParser.getOptions(AarGeneratorOptions.class);

    checkFlags(options);

    try (ScopedTemporaryDirectory scopedTmp = new ScopedTemporaryDirectory("aar_gen_tmp")) {
      Path tmp = scopedTmp.getPath();
      Path resourcesOut = tmp.resolve("merged_resources");
      Files.createDirectories(resourcesOut);
      Path assetsOut = tmp.resolve("merged_assets");
      Files.createDirectories(assetsOut);
      logger.fine(String.format("Setup finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));
      // There aren't any dependencies, but we merge to combine primary resources from different
      // res/assets directories into a single res and single assets directory.
      MergedAndroidData mergedData =
          AndroidResourceMerger.mergeDataAndWrite(
              options.mainData,
              ImmutableList.<DependencyAndroidData>of(),
              ImmutableList.<DependencyAndroidData>of(),
              resourcesOut,
              assetsOut,
              VariantType.LIBRARY,
              null,
              /* filteredResources= */ ImmutableList.<String>of(),
              options.throwOnResourceConflict);
      logger.fine(String.format("Merging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));

      writeAar(
          options.aarOutput,
          mergedData,
          options.manifest,
          options.rtxt,
          options.classes,
          options.proguardSpecs);
      logger.fine(
          String.format("Packaging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));
    } catch (MergeConflictException e) {
      logger.log(Level.SEVERE, e.getMessage());
      throw e;
    } catch (IOException | MergingException e) {
      logger.log(Level.SEVERE, "Error during merging resources", e);
      throw e;
    }
  }

  @VisibleForTesting
  static void checkFlags(AarGeneratorOptions options) {
    List<String> nullFlags = new LinkedList<>();
    if (options.manifest == null) {
      nullFlags.add("manifest");
    }
    if (options.rtxt == null) {
      nullFlags.add("rtxt");
    }
    if (options.classes == null) {
      nullFlags.add("classes");
    }
    if (!nullFlags.isEmpty()) {
      throw new IllegalArgumentException(
          String.format(
              "%s must be specified. Building an .aar without %s is unsupported.",
              Joiner.on(", ").join(nullFlags), Joiner.on(", ").join(nullFlags)));
    }
  }

  @VisibleForTesting
  static void writeAar(
      Path aar,
      final MergedAndroidData data,
      Path manifest,
      Path rtxt,
      Path classes,
      List<Path> proguardSpecs)
      throws IOException {
    try (final ZipOutputStream zipOut =
        new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(aar)))) {
      ZipEntry manifestEntry = new ZipEntry("AndroidManifest.xml");
      manifestEntry.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
      zipOut.putNextEntry(manifestEntry);
      zipOut.write(Files.readAllBytes(manifest));
      zipOut.closeEntry();

      ZipEntry classJar = new ZipEntry("classes.jar");
      classJar.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
      zipOut.putNextEntry(classJar);
      zipOut.write(Files.readAllBytes(classes));
      zipOut.closeEntry();

      ZipDirectoryWriter resWriter = new ZipDirectoryWriter(zipOut, data.getResourceDir(), "res");
      Files.walkFileTree(data.getResourceDir(), resWriter);
      resWriter.writeEntries();

      ZipEntry r = new ZipEntry("R.txt");
      r.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
      zipOut.putNextEntry(r);
      zipOut.write(Files.readAllBytes(rtxt));
      zipOut.closeEntry();

      if (!proguardSpecs.isEmpty()) {
        ZipEntry proguardTxt = new ZipEntry("proguard.txt");
        proguardTxt.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
        zipOut.putNextEntry(proguardTxt);
        for (Path proguardSpec : proguardSpecs) {
          zipOut.write(Files.readAllBytes(proguardSpec));
          zipOut.write("\r\n".getBytes(UTF_8));
        }
        zipOut.closeEntry();
      }

      if (Files.exists(data.getAssetDir()) && data.getAssetDir().toFile().list().length > 0) {
        ZipDirectoryWriter assetWriter =
            new ZipDirectoryWriter(zipOut, data.getAssetDir(), "assets");
        Files.walkFileTree(data.getAssetDir(), assetWriter);
        assetWriter.writeEntries();
      }
    }
    Files.setLastModifiedTime(aar, FileTime.from(DEFAULT_TIMESTAMP));
  }

  private static class ZipDirectoryWriter extends SimpleFileVisitor<Path> {
    private final ZipOutputStream zipOut;
    private final Path root;
    private final String dirName;
    private final Collection<Path> directories = new ArrayList<>();
    private final Collection<Path> files = new ArrayList<>();

    public ZipDirectoryWriter(ZipOutputStream zipOut, Path root, String dirName) {
      this.zipOut = zipOut;
      this.root = root;
      this.dirName = dirName;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      files.add(file);
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        throws IOException {
      directories.add(dir);
      return FileVisitResult.CONTINUE;
    }

    void writeEntries() throws IOException {
      for (Path dir : Ordering.natural().immutableSortedCopy(directories)) {
        writeDirectoryEntry(dir);
      }
      for (Path file : Ordering.natural().immutableSortedCopy(files)) {
        writeFileEntry(file);
      }
    }

    private void writeFileEntry(Path file) throws IOException {
      ZipEntry entry = new ZipEntry(new File(dirName, root.relativize(file).toString()).toString());
      entry.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
      zipOut.putNextEntry(entry);
      zipOut.write(Files.readAllBytes(file));
      zipOut.closeEntry();
    }

    private void writeDirectoryEntry(Path dir) throws IOException {
      ZipEntry entry =
          new ZipEntry(new File(dirName, root.relativize(dir).toString()).toString() + "/");
      entry.setTime(DEFAULT_TIMESTAMP.toEpochMilli());
      zipOut.putNextEntry(entry);
      zipOut.closeEntry();
    }
  }
}
