/*
 * 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.zip;

import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import com.google.common.io.Files;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;

/**
 * Command to zip up a directory while respecting a file size limit to be deflated.
 * <p>
 * Currently, Froyo has a limitation where it will not deflate files out of a zip if the inflated
 * size exceeds 1 MiB (1 << 20 bytes).  This utility is useful for including assets into the APK
 * where we deflate those that we can, and store the ones we can't.
 */
public class ZipDirectoryWithMaxDeflateStep implements Step {

  /**
   * Extensions of files we don't want to DEFLATE (e.g. already compressed).
   */
  private final Set<String> EXTENSIONS_NOT_TO_DEFLATE = ImmutableSet.of(
      "gzip",
      "jar",
      "jpg",
      "png",
      "xz"
  );

  private final String inputDirectoryPath;
  private final String outputZipPath;
  private final long maxDeflatedBytes;

  public ZipDirectoryWithMaxDeflateStep(String inputDirectoryPath, String outputZipPath) {
    this(inputDirectoryPath, outputZipPath, 0);
  }

  public ZipDirectoryWithMaxDeflateStep(String inputDirectoryPath,
                                        String outputZipPath,
                                        long maxDeflatedBytes) {
    Preconditions.checkState(maxDeflatedBytes >= 0);

    this.maxDeflatedBytes = maxDeflatedBytes;
    this.inputDirectoryPath = Preconditions.checkNotNull(inputDirectoryPath);
    this.outputZipPath = Preconditions.checkNotNull(outputZipPath);
  }

  @Override
  public int execute(ExecutionContext context) {
    File inputDirectory = new File(inputDirectoryPath);
    Preconditions.checkState(inputDirectory.exists() && inputDirectory.isDirectory(),
        "%s must be a directory.",
        inputDirectoryPath);

    Closer closer = Closer.create();
    try {
      ImmutableMap.Builder<File, ZipEntry> zipEntriesBuilder = ImmutableMap.builder();
      addDirectoryToZipEntryList(inputDirectory, "", zipEntriesBuilder);
      ImmutableMap<File, ZipEntry> zipEntries = zipEntriesBuilder.build();

      if (!zipEntries.isEmpty()) {
        CustomZipOutputStream outputStream = closer.register(
            ZipOutputStreams.newOutputStream(new BufferedOutputStream(
                new FileOutputStream(outputZipPath))));

        for (Map.Entry<File, ZipEntry> zipEntry : zipEntries.entrySet()) {
          outputStream.putNextEntry(zipEntry.getValue());
          ByteStreams.copy(Files.newInputStreamSupplier(zipEntry.getKey()), outputStream);
          outputStream.closeEntry();
        }
      }
    } catch (IOException e) {
      e.printStackTrace(context.getStdErr());
      return 1;
    } finally {
      try {
        closer.close();
      } catch (IOException e) {
        Throwables.propagate(e);
      }
    }
    return 0;
  }

  private void addDirectoryToZipEntryList(File directory,
                                 String currentPath,
                                 ImmutableMap.Builder<File, ZipEntry> zipEntriesBuilder)
      throws IOException {
    Preconditions.checkNotNull(currentPath);

    for (File inputFile : directory.listFiles()) {
      String childPath = currentPath +
          (currentPath.isEmpty() ? "" : "/") +
          inputFile.getName();

      if (inputFile.isDirectory()) {
        addDirectoryToZipEntryList(inputFile, childPath, zipEntriesBuilder);
      } else {
        ZipEntry nextEntry = new ZipEntry(childPath);
        long fileLength = inputFile.length();
        if (fileLength > maxDeflatedBytes ||
            EXTENSIONS_NOT_TO_DEFLATE.contains(Files.getFileExtension(inputFile.getName()))) {
          nextEntry.setMethod(ZipEntry.STORED);
          nextEntry.setCompressedSize(inputFile.length());
          nextEntry.setSize(inputFile.length());
          HashCode crc = ByteStreams.hash(Files.newInputStreamSupplier(inputFile), Hashing.crc32());
          nextEntry.setCrc(crc.padToLong());
        }

        zipEntriesBuilder.put(inputFile, nextEntry);
      }
    }
  }

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

  @Override
  public String getDescription(ExecutionContext context) {
    return String.format("zip -r %s %s", outputZipPath, inputDirectoryPath);
  }
}
