// Copyright 2017 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 com.google.common.base.Predicates.not;

import com.android.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.android.AndroidResourceOutputs.ZipBuilder;
import com.google.devtools.build.android.AndroidResourceOutputs.ZipBuilderVisitorWithDirectories;
import com.google.devtools.build.android.aapt2.ProtoApk;
import com.google.devtools.build.android.aapt2.ProtoResourceUsageAnalyzer;
import com.google.devtools.build.android.aapt2.ResourceLinker;
import com.google.devtools.build.android.proto.SerializeFormat.ToolAttributes;
import com.google.protobuf.ExtensionRegistry;
import java.io.Closeable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

/** Represents a collection of raw, merged resources with an optional id list. */
public class ResourcesZip {

  static final Logger logger = Logger.getLogger(ResourcesZip.class.toString());

  @Nullable private final Path resourcesRoot;
  @Nullable private final Path assetsRoot;
  @Nullable private final Path apkWithAssets;
  @Nullable private final Path proto;
  @Nullable private final Path attributes;
  @Nullable private final Path packages;
  @Nullable private final Path ids;

  private ResourcesZip(
      @Nullable Path resourcesRoot,
      @Nullable Path assetsRoot,
      @Nullable Path ids,
      @Nullable Path apkWithAssets,
      @Nullable Path proto,
      @Nullable Path attributes,
      @Nullable Path packages) {
    this.resourcesRoot = resourcesRoot;
    this.assetsRoot = assetsRoot;
    this.ids = ids;
    this.apkWithAssets = apkWithAssets;
    this.proto = proto;
    this.attributes = attributes;
    this.packages = packages;
  }

  /**
   * @param resourcesRoot The root of the raw resources.
   * @param assetsRoot The root of the raw assets.
   */
  public static ResourcesZip from(Path resourcesRoot, Path assetsRoot) {
    return new ResourcesZip(resourcesRoot, assetsRoot, null, null, null, null, null);
  }

  /**
   * @param proto apk in proto format.
   * @param attributes Tooling attributes.
   * @param resourceIds Optional path to a file containing the resource ids.
   * @param packages Optional path to a file containing the dependency packages.
   */
  public static ResourcesZip fromApkWithProto(
      Path proto, Path attributes, Path resourceIds, Path packages) {
    return new ResourcesZip(
        /* resourcesRoot= */ null,
        /* assetsRoot= */ null,
        resourceIds != null && Files.exists(resourceIds) ? resourceIds : null,
        /* apkWithAssets= */ null,
        proto,
        attributes,
        packages);
  }

  /** Creates a ResourcesZip from an archive by expanding into the workingDirectory. */
  public static ResourcesZip createFrom(Path resourcesZip, Path workingDirectory)
      throws IOException {
    // Expand resource files zip into working directory.
    final ZipFile zipFile = new ZipFile(resourcesZip.toFile());

    zipFile.stream()
        .filter(not(ZipEntry::isDirectory))
        .forEach(
            entry -> {
              Path output = workingDirectory.resolve(entry.getName());
              try {
                Files.createDirectories(output.getParent());
                try (FileOutputStream fos = new FileOutputStream(output.toFile())) {
                  ByteStreams.copy(zipFile.getInputStream(entry), fos);
                }
              } catch (IOException e) {
                throw new RuntimeException(e);
              }
            });
    return new ResourcesZip(
        Files.createDirectories(workingDirectory.resolve("res")),
        Files.createDirectories(workingDirectory.resolve("assets")),
        ifExists(workingDirectory.resolve("ids.txt")),
        /** apkWithAssets */
        null,
        ifExists(workingDirectory.resolve("apk.pb")),
        ifExists(workingDirectory.resolve("tools.attributes.pb")),
        ifExists(workingDirectory.resolve("packages.txt")));
  }

  private static Path ifExists(Path path) {
    return Files.exists(path) ? path : null;
  }

  /**
   * Creates a zip file containing the provided android resources and assets.
   *
   * @param output The path to write the zip file
   * @param compress Whether or not to compress the content
   * @throws IOException
   */
  public void writeTo(Path output, boolean compress) throws IOException {
    try (final ZipBuilder zip = ZipBuilder.createFor(output)) {
      if (resourcesRoot != null && Files.exists(resourcesRoot)) {
        ZipBuilderVisitorWithDirectories visitor =
            new ZipBuilderVisitorWithDirectories(zip, resourcesRoot, "res");
        visitor.setCompress(compress);
        Files.walkFileTree(resourcesRoot, visitor);
        if (!Files.exists(resourcesRoot.resolve("values/public.xml"))) {
          // add an empty public xml, if one doesn't exist. The ResourceUsageAnalyzer expects one.
          visitor.addEntry(
              resourcesRoot.resolve("values").resolve("public.xml"),
              "<resources></resources>".getBytes(StandardCharsets.UTF_8));
        }
        visitor.writeEntries();
      }

      if (apkWithAssets != null && Files.exists(apkWithAssets)) {
        ZipFile apkZip = new ZipFile(apkWithAssets.toString());
        if (apkZip.getEntry("assets/") == null) {
          zip.addEntry("assets/", new byte[0], compress ? ZipEntry.DEFLATED : ZipEntry.STORED);
        }
        apkZip.stream()
            .filter(entry -> entry.getName().startsWith("assets/"))
            .forEach(
                entry -> {
                  try {
                    zip.addEntry(entry, ByteStreams.toByteArray(apkZip.getInputStream(entry)));
                  } catch (IOException e) {
                    throw new RuntimeException(e);
                  }
                });
      } else if (assetsRoot != null && Files.exists(assetsRoot)) {
        ZipBuilderVisitorWithDirectories visitor =
            new ZipBuilderVisitorWithDirectories(zip, assetsRoot, "assets");
        visitor.setCompress(compress);
        Files.walkFileTree(assetsRoot, visitor);
        visitor.writeEntries();
      }
      try {
        if (ids != null) {
          zip.addEntry("ids.txt", Files.readAllBytes(ids), ZipEntry.STORED);
        }

        if (proto != null && Files.exists(proto)) {
          zip.addEntry("apk.pb", Files.readAllBytes(proto), ZipEntry.STORED);
        }

        if (attributes != null && Files.exists(attributes)) {
          zip.addEntry("tools.attributes.pb", Files.readAllBytes(attributes), ZipEntry.STORED);
        }

        if (packages != null && Files.exists(packages)) {
          zip.addEntry("packages.txt", Files.readAllBytes(packages), ZipEntry.STORED);
        }

      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Shrinks the apk using a protocol buffer apk.
   *
   * @param packages The packages of the dependencies. Used to analyze the java code for resource
   *     references.
   * @param classJar Used to find resource references in java.
   * @param rTxt R.txt file listing all resources.
   * @param proguardMapping Mapping used to decode java references.
   * @param logFile Destination of the resource shrinker log.
   * @param workingDirectory Temporary directory for intermediate artifacts.
   * @return A ShrunkProtoApk, which must be closed when finished.
   * @throws ParserConfigurationException thrown when the xml parsing not possible.
   * @throws IOException thrown when the filesystem is going pear shaped.
   * @throws SAXException thrown when the xml parsing goes badly.
   */
  @CheckReturnValue
  public ShrunkProtoApk shrinkUsingProto(
      Set<String> packages,
      Path classJar,
      Path rTxt,
      Path proguardMapping,
      Path logFile,
      Path workingDirectory)
      throws ParserConfigurationException, IOException {
    Path shrunkApkProto = workingDirectory.resolve("shrunk." + ResourceLinker.PROTO_EXTENSION);
    Path resourcesConfig = workingDirectory.resolve("resources.cfg");

    try (final ProtoApk apk = ProtoApk.readFrom(proto)) {
      // record resources and manifest
      final ProtoResourceUsageAnalyzer analyzer =
          new ProtoResourceUsageAnalyzer(packages, rTxt, proguardMapping, resourcesConfig, logFile);

      ProtoApk shrink = analyzer.shrink(apk, classJar, shrunkApkProto, parseToolAttributes());
      return new ShrunkProtoApk(shrink, resourcesConfig, logFile, ids);
    }
  }

  @VisibleForTesting
  ImmutableListMultimap<String, String> parseToolAttributes() throws IOException {
    return ToolAttributes.parseFrom(
            Files.readAllBytes(attributes), ExtensionRegistry.getEmptyRegistry())
        .getAttributesMap()
        .entrySet()
        .stream()
        .collect(
            ImmutableListMultimap.flatteningToImmutableListMultimap(
                Entry::getKey, e -> e.getValue().getValuesList().stream()));
  }

  public List<String> asPackages() throws IOException {
    return packages != null
        ? Files.readAllLines(packages, StandardCharsets.UTF_8)
        : ImmutableList.of();
  }

  Path asApk() {
    return proto;
  }

  static class ShrunkProtoApk implements Closeable {
    private final ProtoApk apk;
    private final Path resourcesConfig;
    private final Path report;
    private final Path ids;

    ShrunkProtoApk(ProtoApk apk, Path resourcesConfig, Path report, Path ids) {
      this.apk = apk;
      this.resourcesConfig = resourcesConfig;
      this.report = report;
      this.ids = ids;
    }

    ShrunkProtoApk writeBinaryTo(ResourceLinker linker, Path binaryOut, boolean writeAsProto)
        throws IOException {
      Files.copy(
          writeAsProto ? apk.asApkPath() : linker.link(apk, ids),
          binaryOut,
          StandardCopyOption.REPLACE_EXISTING);
      return this;
    }

    void writeResourcesConfigTo(Path resourcesConfigOut) throws Exception {
      Files.copy(resourcesConfig, resourcesConfigOut);
    }

    ShrunkProtoApk writeReportTo(Path reportOut) throws IOException {
      Files.copy(report, reportOut);
      return this;
    }

    ShrunkProtoApk writeResourcesToZip(Path resourcesZip) throws IOException {
      try (final ZipBuilder zip = ZipBuilder.createFor(resourcesZip)) {
        zip.addEntry("apk.pb", Files.readAllBytes(apk.asApkPath()), ZipEntry.STORED);
      }
      return this;
    }

    @Override
    public void close() throws IOException {
      apk.close();
    }
  }
}
