// 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.ziputils;

import static com.google.devtools.build.android.ziputils.DataDescriptor.EXTLEN;
import static com.google.devtools.build.android.ziputils.DataDescriptor.EXTSIZ;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENLEN;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENOFF;
import static com.google.devtools.build.android.ziputils.DirectoryEntry.CENSIZ;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDOFF;
import static com.google.devtools.build.android.ziputils.EndOfCentralDirectory.ENDSUB;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Map;

/**
 * API for reading a zip file. This does not perform decompression of entry data, but provides
 * a raw view of the content of a zip archive.
 */
public class ZipIn {

  private static final byte[] EOCD_SIG = {0x50, 0x4b, 0x05, 0x06};
  private static final byte[] HEADER_SIG = {0x50, 0x4b, 0x03, 0x04};
  private static final byte[] DATA_DESC_SIG = {0x50, 0x4b, 0x07, 0x08};


  /**
   * Max end-of-central-directory size, including variable length file comment..
   */
  private static final int MAX_EOCD_SIZE = 1024;

  /**
   * Max local file header size, including long filename.
   */
  private static final int MAX_HEADER_SIZE = 64 * 1024;

  /**
   * Default size of direct byte buffer used for reading content. Actual allocation will not
   * exceed the archive content size, and may be at least as big as the largest entry.
   */
  private static final int READ_BLOCK_SIZE = 20 * 1024 * 1024;

  private final String filename; // filename or nickname.
  private final FileChannel fileChannel; // input file.
  private BufferedFile bufferedFile;
  private CentralDirectory cdir = null;
  private EndOfCentralDirectory eocd = null;
  private final boolean useDirectory;
  private final boolean ignoreDeleted;
  private final boolean verbose = false;

  /**
   * Creates a {@code ZipIn} view of a file, with a (nick)name.
   *
   * @param channel File channel open for reading.
   * @param filename filename or nickname.
   */
  public ZipIn(FileChannel channel, String filename) {
    this.fileChannel = channel;
    this.filename = filename;
    this.useDirectory = true;
    this.ignoreDeleted = useDirectory;
  }

  /**
   * Gets the file name for this zip input file.
   * @return the filename set at time of construction.
   */
  public String getFilename() {
    return filename;
  }

  /**
   * Returns a view of the "end of central directory" record expected at (or towards) the end of a
   * zip file.
   *
   * @return A read-only, {@link EndOfCentralDirectory}.
   * @throws IOException
   */
  public EndOfCentralDirectory endOfCentralDirectory() throws IOException {
    if (eocd == null) {
      loadEndOfCentralDirectory();
    }
    return eocd;
  }

  /**
   * Returns a memory mapped view of the central directory.
   *
   * @return A read-only, {@link CentralDirectory} of the central directory.
   * @throws IOException
   */
  public CentralDirectory centralDirectory() throws IOException {
    if (cdir == null) {
      loadCentralDirectory();
    }
    return cdir;
  }

  /**
   * Scans all entries in the zip file and invokes the given {@link EntryHandler} on each.
   *
   * @param handler handler to invoke for each file entry.
   * @throws IOException
   */
  public void scanEntries(EntryHandler handler) throws IOException {
    centralDirectory();
    ZipEntry zipEntry = nextFrom(null);
    while (zipEntry.getCode() != ZipEntry.Status.ENTRY_NOT_FOUND) {
      if (zipEntry.getCode() != ZipEntry.Status.ENTRY_OK) {
        throw new IOException(zipEntry.getCode().toString());
      }
      handler.handle(this, zipEntry.getHeader(), zipEntry.getDirEntry(), zipEntry.getContent());
      if (useDirectory && ignoreDeleted) {
        zipEntry = ZipIn.this.nextFrom(zipEntry.getDirEntry());
      } else {
        zipEntry = nextFrom(zipEntry.limit());
      }
    }
  }

  /**
   * Finds the next header, by scanning for a local header signature starting
   * at {@code offset}. This method will find headers for deleted or updated entries that
   * are not listed in the central directory, and may pickup false positive (e.g. entries
   * of an embedded zip file stored without compression). This method is primarily intended
   * for applications trying to recover data from corrupt archives.
   *
   * @param offset offset where to start the search.
   * @return the next local header at or beyond {@code offset}, or {@code null} if no
   * header is found.
   * @throws IOException
   */
  public LocalFileHeader nextHeaderFrom(long offset) throws IOException {
    int skipped = 0;
    for (ByteBuffer buffer = getData(offset + skipped, MAX_HEADER_SIZE);
        buffer.limit() >= LocalFileHeader.SIZE;
        buffer = getData(offset + skipped, MAX_HEADER_SIZE)) {
      int markerOffset = ScanUtil.scanTo(HEADER_SIG, buffer);
      if (markerOffset < 0) {
        skipped += buffer.limit() - 3;
      } else {
        skipped += markerOffset;
        LocalFileHeader header =  markerOffset == 0 ? localHeaderIn(buffer, offset + skipped)
            : localHeaderAt(offset + skipped);
        if (header != null) {
          if (skipped > 0) {
            System.out.println("Warning: local header search: skipped " + skipped + " bytes");
          }
          return header;
        }
        // If localHeaderIn or localHeaderAt decided it is not a header location,
        // we continue the search.
        skipped += 4;
      }
    }
    return null;
  }

  /**
   * Finds the header at the next higher offset listed in the central directory as containing
   * a local file header, starting from the offset of the given {@code dirEntry}. This method will
   * bypass any deleted or updated entries not listed in the directory, and also any entries from
   * embedded zip files, or random instance of the header signature. This is the preferred method
   * for sequentially reading the entries of a valid zip file.
   *
   * @param dirEntry directory entry for the "current entry", providing the start point
   * for searching the central directory for the entry with the next higher offset.
   * @return the next header according to the central directory, or {@code null} if there are no
   * more headers.
   * @throws IOException
   */
  public LocalFileHeader nextHeaderFrom(DirectoryEntry dirEntry) throws IOException {
    Integer nextOffset = dirEntry == null ? -1 : dirEntry.get(CENOFF);
    while ((nextOffset = cdir.mapByOffset().higherKey(nextOffset)) != null) {
      LocalFileHeader header = localHeaderAt(nextOffset);
      if (header != null) {
        return header;
      }
      System.out.println("Warning: no header for file listed in directory "
          + dirEntry.getFilename());
      // The file is corrupt! Continue to see how bad it is.
    }
    return null;
  }

  /**
   * Provides a {@code LocalFileHeader} view of a local header located at the offset indicated
   * by the given {@code dirEntry}.
   *
   * @param dirEntry the directory entry referring to the headers location.
   * @return the requested header, or {@code null} if the given location can't possibly contain a
   * valid file header (e.g. missing header signature), or if {@code dirEntry} is {@code null}.
   * @throws IOException
   */
  public LocalFileHeader localHeaderFor(DirectoryEntry dirEntry) throws IOException {
    return dirEntry == null ? null : localHeaderAt(dirEntry.get(CENOFF));
  }

  /**
   * Provides a {@code LocalFileHeader} view of a local header located at the offset indicated
   * by the given {@code dirEntry}.
   *
   * @param offset offset a which the a header is presumed to exist.
   * @return the requested header, or {@code null} if the given location can't possibly contain a
   * valid file header (e.g. missing header signature).
   * @throws IOException
   */
  public LocalFileHeader localHeaderAt(long offset) throws IOException {
    return localHeaderIn(getData(offset, MAX_HEADER_SIZE), offset);
  }

  /**
   * Finds the next zip file entry, by scanning for a local header using the
   * {@link #nextHeaderFrom(long) }method.
   *
   * @param offset offset where to start the search.
   * @return a {@code ZipEntry} object with the result of the search.
   * @throws IOException
   */
  public ZipEntry nextFrom(long offset) throws IOException {
    LocalFileHeader header = ZipIn.this.nextHeaderFrom(offset);
    return entryWith(header);
  }

  /**
   * Finds the next zip file entry, by first invoking
   * {@link #nextHeaderFrom(com.google.devtools.build.android.ziputils.DirectoryEntry) }
   * to find its header.
   *
   * @param entry the directory entry for the "current" zip entry, or {@code null} to get
   * the first entry.
   * @return a {@code ZipEntry} object with the result of the search.
   * @throws IOException
   */
  public ZipEntry nextFrom(DirectoryEntry entry) throws IOException {
    int offset = entry == null ? -1 : entry.get(CENOFF);
    Map.Entry<Integer, DirectoryEntry> mapEntry = cdir.mapByOffset().higherEntry(offset);
    if (mapEntry == null) {
      return entryWith(null);
    }
    LocalFileHeader header = localHeaderAt(mapEntry.getKey());
    return entryWith(header, mapEntry.getValue());
  }
  
  /**
   * Finds the zip file entry, for a given directory entry.
   *
   * @param entry the directory entry for which a zip entry is requested.
   * @return a {@code ZipEntry} object with the result of the search.
   * @throws IOException
   */
  public ZipEntry entryFor(DirectoryEntry entry) throws IOException {
    return entryWith(localHeaderFor(entry), entry);
  }

  /**
   * Returns the zip file entry at the given offset.
   *
   * @param offset presumed location of local file header.
   * @return a {@link ZipEntry} for the given location.
   * @throws IOException
   */
  public ZipEntry entryAt(long offset) throws IOException {
    LocalFileHeader header = localHeaderAt(offset);
    return entryWith(header);
  }

  /**
   * Constructs a {@link ZipEntry} view of the entry at the location of the given header.
   *
   * @param header a previously located header. If (@code useDirectory} is set, this will
   * attempt to lookup a corresponding directory entry. If there is none, and {@code ignoreDeleted}
   * is also set, the return value will flag this entry with a
   * {@code ZipEntry.Status.ENTRY_NOT_FOUND} status code.
   *
   * @return  {@link ZipEntry} for the given location.
   * @throws IOException
   */
  public ZipEntry entryWith(LocalFileHeader header) throws IOException {
    if (header == null) {
      return new ZipEntry().withCode(ZipEntry.Status.ENTRY_NOT_FOUND);
    }
    // header != null
    long offset = header.fileOffset();
    DirectoryEntry dirEntry = null;
    if (useDirectory) {
      dirEntry = cdir.mapByOffset().get((int) offset);
      if (dirEntry == null && ignoreDeleted) {
        return new ZipEntry().withCode(ZipEntry.Status.ENTRY_DELETED);
      }
    }
    return entryWith(header, dirEntry);
  }

  /**
   * Scans for a data descriptor from a given offset.
   *
   * @param offset position where to start the search.
   * @param dirEntry directory entry for validation, or {@code null}.
   * @return A data descriptor view for the next position containing the data descriptor signature.
   * @throws IOException
   */
  public DataDescriptor descriptorFrom(final long offset, final DirectoryEntry dirEntry)
      throws IOException {
    int skipped = 0;
    for (ByteBuffer buffer = getData(offset + skipped, MAX_HEADER_SIZE);
        buffer.limit() >= 16; buffer = getData(offset + skipped, MAX_HEADER_SIZE)) {
      int markerOffset = ScanUtil.scanTo(DATA_DESC_SIG, buffer);
      if (markerOffset < 0) {
        skipped += buffer.limit() - 3;
      } else {
        skipped += markerOffset;
        return markerOffset == 0 ? descriptorIn(buffer, offset + skipped, dirEntry)
            : descriptorAt(offset + skipped, dirEntry);
      }
    }
    return null;
  }

  /**
   * Creates a data descriptor view at a given offset.
   *
   * @param offset presumed location of data descriptor.
   * @param dirEntry directory entry to use for validation, or {@code null}.
   * @return a data descriptor view over the given file offset.
   * @throws IOException
   */
  public DataDescriptor descriptorAt(long offset, DirectoryEntry dirEntry) throws IOException {
    return descriptorIn(getData(offset, 16), offset, dirEntry);
  }

  /**
   * Constructs a zip entry object for the location of the given header, with the corresponding
   * directory entry.
   *
   * @param header local file header for the entry.
   * @param dirEntry corresponding directory entry, or {@code null} if not available.
   * @return a zip entry with the given header and directory entry.
   * @throws IOException
   */
  private ZipEntry entryWith(LocalFileHeader header, DirectoryEntry dirEntry) throws IOException {
    ZipEntry zipEntry = new ZipEntry().withHeader(header).withEntry(dirEntry);
    int offset = (int) (header.fileOffset() + header.getSize());
    // !useDirectory || dirEntry != null || !ignoreDeleted
    String entryName = header.getFilename();
    if (dirEntry != null && !entryName.equals(dirEntry.getFilename())) {
      return zipEntry.withEntry(dirEntry).withCode(ZipEntry.Status.FILENAME_ERROR);
    }
    int sizeByHeader = header.dataSize();
    int sizeByDir = dirEntry != null ? dirEntry.dataSize() : -1;
    ByteBuffer content;
    if (sizeByDir == sizeByHeader && sizeByDir >= 0) {
      // Ideal case, header and directory in agreement
      content = getData(offset, sizeByHeader);
      if (content.limit() == sizeByHeader) {
        return zipEntry.withContent(content).withCode(ZipEntry.Status.ENTRY_OK);
      } else {
        return zipEntry.withContent(content).withCode(ZipEntry.Status.NOT_ENOUGH_DATA);
      }
    }
    if (sizeByDir >= 0) {
      // If file is correct, we get here because of a 0x8 flag, and we expect
      // data to be followed by a data descriptor.
      content = getData(offset, sizeByDir);
      DataDescriptor dataDesc = descriptorAt(offset + sizeByDir, dirEntry);
      if (dataDesc != null) {
        return zipEntry.withContent(content).withDescriptor(dataDesc).withCode(
            ZipEntry.Status.ENTRY_OK);
      }
      return zipEntry.withContent(content).withCode(ZipEntry.Status.NO_DATA_DESC);
    }
    if (!ignoreDeleted) {
      if (sizeByHeader >= 0) {
        content = getData(offset, sizeByHeader);
        if (content.limit() == sizeByHeader) {
          return zipEntry.withContent(content).withCode(ZipEntry.Status.ENTRY_OK);
        }
        return zipEntry.withContent(content).withCode(ZipEntry.Status.NOT_ENOUGH_DATA);
      } else {

        DataDescriptor dataDesc = descriptorFrom(offset, dirEntry);
        if (dataDesc == null) {
          // Only way now would be to decompress
          return zipEntry.withCode(ZipEntry.Status.UNKNOWN_SIZE);
        }
        int sizeByDesc = dataDesc.get(EXTSIZ);
        if (sizeByDesc != dataDesc.fileOffset() - offset) {
          // That just can't be the right
          return zipEntry.withDescriptor(dataDesc).withCode(ZipEntry.Status.UNKNOWN_SIZE);
        }
        content = getData(offset, sizeByDesc);
        return zipEntry.withContent(content).withDescriptor(dataDesc).withCode(
            ZipEntry.Status.ENTRY_OK);
      }
    }
    return zipEntry.withCode(ZipEntry.Status.UNKNOWN_SIZE);
  }

  /**
   * Constructs a local header view over a give byte buffer.
   *
   * @param buffer byte buffer with local header data.
   * @param offset file offset at which the buffer is based.
   * @return a local header view.
   */
  private LocalFileHeader localHeaderIn(ByteBuffer buffer, long offset) {
    return buffer.limit() < LocalFileHeader.SIZE
        || buffer.getInt(0) != LocalFileHeader.SIGNATURE
        ? null : LocalFileHeader.viewOf(buffer).at(offset);
  }

  /**
   * Constructs a data descriptor view over a given byte buffer.
   *
   * @param buf byte buffer with data descriptor data.
   * @param offset file offset at which the buffer is based.
   * @param dirEntry directory entry with presumed reliable content size information.
   * @return a data descriptor
   */
  private DataDescriptor descriptorIn(ByteBuffer buf, long offset, DirectoryEntry dirEntry) {
    if (buf.limit() < 12) {
      return null;
    }
    DataDescriptor desc = DataDescriptor.viewOf(buf).at(offset);
    if (desc.hasMarker() || (dirEntry != null
        && desc.get(EXTSIZ) == dirEntry.get(CENSIZ)
        && desc.get(EXTLEN) == dirEntry.get(CENLEN))) {
      return desc;
    }
    return null;
  }

  /**
   * Obtains a byte buffer at a given offset.
   */
  private ByteBuffer getData(long offset, int size) throws IOException {
    return bufferedFile.getBuffer(offset, size).order(ByteOrder.LITTLE_ENDIAN);
  }

  /**
   * Locates the "end of central directory" record, expected located at the end of the file, and
   * reads it into a byte buffer. Called on the first invocation of
   * {@link #endOfCentralDirectory() }.
   *
   * @throws IOException
   */
  protected void loadEndOfCentralDirectory() throws IOException {
    cdir = null;
    long size = fileChannel.size();
    verbose("Loading ZipIn: " + filename);
    verbose("-- size: " + size);
    int cap = (int) Math.min(size, MAX_EOCD_SIZE);
    ByteBuffer buffer = ByteBuffer.allocate(cap).order(ByteOrder.LITTLE_ENDIAN);
    long offset = size - cap;
    while (true) {
      fileChannel.position(offset);
      while (buffer.hasRemaining()) {
        fileChannel.read(buffer, offset);
      }
      // scan to find it...
      int endOfDirOffset = ScanUtil.scanBackwardsTo(EOCD_SIG, buffer);
      if (endOfDirOffset < 0) {
        if (offset == 0) {
          if (useDirectory) {
            throw new IllegalStateException("No end of central directory marker");
          } else {
            break;
          }
        }
        offset = Math.max(offset - 1000, 0);
        buffer.clear();
        continue;
      }
      long eocdFileOffset = offset + endOfDirOffset;
      verbose("-- EOCD: " + eocdFileOffset + " size: " + (size - eocdFileOffset));
      buffer.position(endOfDirOffset);
      eocd = EndOfCentralDirectory.viewOf(buffer).at(offset + endOfDirOffset);
      // TODO (bazel-team): check that the end of central directory, points to a valid
      // first directory entry. If not, assume we happened to find the signature inside
      // a file comment, and resume the search.
      break;
    }

    if (eocd != null) {
      bufferedFile = new BufferedFile(fileChannel, 0, eocd.get(ENDOFF),
          READ_BLOCK_SIZE);
    } else {
      bufferedFile = new BufferedFile(fileChannel, READ_BLOCK_SIZE);
    }
  }

  /**
   * Maps the central directory to memory. Called on the first invocation of
   * {@link #centralDirectory() }.
   *
   * @throws IOException
   */
  protected void loadCentralDirectory() throws IOException {
    if (eocd == null) {
      loadEndOfCentralDirectory();
    }
    if (eocd == null) {
      return;
    }
    long cdOffset = eocd.get(ENDOFF);
    long len = eocd.fileOffset() - cdOffset;
    verbose("-- CDIR: " + cdOffset + " size: " + len + " count: " + eocd.get(ENDSUB));
    // Read directory to buffer.
    // TODO(bazel-team): we currently assume the directory fits in memory (and int).
    ByteBuffer buffer = ByteBuffer.allocateDirect((int) len);
    while (len > 0) {
      int read = fileChannel.read(buffer, cdOffset);
      len -= read;
      cdOffset += read;
    }
    buffer.rewind();
    cdir = CentralDirectory.viewOf(buffer).at(cdOffset).parse();
    cdir.buffer.flip();
  }

  /**
   * Zip file entry container class, for use with the low-level scanning operations of this
   * API, supporting zip file scanner construction.
   */
  public static class ZipEntry {

    private LocalFileHeader header;
    private DataDescriptor descriptor;
    private ByteBuffer content;
    private DirectoryEntry entry;
    private Status code;

    /**
     * Creates a zip entry, setting the initial status to not found.
     */
    public ZipEntry() {
      code = Status.ENTRY_NOT_FOUND;
    }

    /**
     * Gets the header of this zip entry.
     */
    public LocalFileHeader getHeader() {
      return header;
    }

    /**
     * Sets the header of this zip entry.
     * @return this object.
     */
    public ZipEntry withHeader(LocalFileHeader header) {
      this.header = header;
      return this;
    }

    /**
     * Gets the data descriptor of this zip entry, if any.
     */
    public DataDescriptor getDescriptor() {
      return descriptor;
    }

    /**
     * Sets the data descriptor of this zip entry.
     * @return this object.
     */
    public ZipEntry withDescriptor(DataDescriptor descriptor) {
      this.descriptor = descriptor;
      return this;
    }

    /**
     * Gets a byte buffer for accessing the raw content of this zip entry.
     */
    public ByteBuffer getContent() {
      return content;
    }

    /**
     * Sets the byte buffer providing access to the raw content of this zip entry.
     * @return this object
     */
    public ZipEntry withContent(ByteBuffer content) {
      this.content = content;
      return this;
    }

    /**
     * Gets the central directory entry for this zip entry, if any.
     */
    public DirectoryEntry getDirEntry() {
      return entry;
    }

    /**
     * Sets the central directory entry for this zip entry.
     * @return this object.
     */
    public ZipEntry withEntry(DirectoryEntry entry) {
      this.entry = entry;
      return this;
    }

    /**
     * Gets the status code for parsing this zip entry.
     */
    public Status getCode() {
      return code;
    }

    /**
     * Sets the status code for this zip entry.
     * @return this object.
     */
    public ZipEntry withCode(Status code) {
      this.code = code;
      return this;
    }

    /**
     * Calculates, best-effort, the file offset just past this zip entry.
     */
    public long limit() {
      if (header == null) {
        return 0;
      }
      if (descriptor != null) {
        return descriptor.fileOffset() + descriptor.getSize();
      }
      long offset = header.fileOffset() + header.dataSize();
      if (content != null) {
        offset += content.limit();
      }
      return offset;
    }

    /**
     * Zip entry parsing status codes.
     */
    public enum Status {
      /**
       * This zip entry contains valid header and data
       */
      ENTRY_OK,
      /**
       * No header at the given location
       */
      ENTRY_NOT_FOUND,
      /**
       * The given location contains a header that is not listed in the central directory
       */
      ENTRY_DELETED,
      /**
       * The header in the given location has a different filename than the
       * directory entry for this location.
       */
      FILENAME_ERROR,
      /**
       * The given location has the header signature, but the remaining data is insufficient
       * to constitute a complete entry.
       */
      NOT_ENOUGH_DATA,
      /**
       * The entry appears to be missing an expected data descriptor.
       */
      NO_DATA_DESC,
      /**
       * The implementation was unable to determine the size of the content of the entry.
       * The client will have to either parse using the central directory, or if all else
       * fails, attempt to decompress the entry.
       */
      UNKNOWN_SIZE,
    }
  }

  private void verbose(String msg) {
    if (verbose) {
      System.out.println(msg);
    }
  }
}
