// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package multidex004.fakelibrary;

import java.io.Closeable;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;
import multidex004.fakeframeworks.Context;

/** Exposes application secondary dex files as files in the application data directory. */
final class MultiDexExtractor {

  private static final String TAG = MultiDex.TAG;

  /** We look for additional dex files named {@code classes2.dex}, {@code classes3.dex}, etc. */
  private static final String DEX_PREFIX = "classes";

  private static final String DEX_SUFFIX = ".dex";

  private static final String EXTRACTED_NAME_EXT = ".classes";
  private static final String EXTRACTED_SUFFIX = ".zip";
  private static final int MAX_EXTRACT_ATTEMPTS = 3;

  private static final String PREFS_FILE = "multidex.version";
  private static final String KEY_TIME_STAMP = "timestamp";
  private static final String KEY_CRC = "crc";
  private static final String KEY_DEX_NUMBER = "dex.number";

  /** Size of reading buffers. */
  private static final int BUFFER_SIZE = 0x4000;

  /* Keep value away from 0 because it is a too probable time stamp value */
  private static final long NO_VALUE = -1L;

  private static List<File> loadExistingExtractions(Context context, File sourceApk, File dexDir)
      throws IOException {

    final String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;
    int totalDexNumber = 1;
    final List<File> files = null;

    for (int secondaryNumber = 2; secondaryNumber <= totalDexNumber; secondaryNumber++) {
      String fileName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX;
      File extractedFile = new File(dexDir, fileName);
      if (extractedFile.isFile()) {
        files.add(extractedFile);
      } else {
        throw new IOException(
            "Missing extracted secondary dex file '" + extractedFile.getPath() + "'");
      }
    }

    return files;
  }

  private static long getTimeStamp(File archive) {
    long timeStamp = archive.lastModified();
    if (timeStamp == NO_VALUE) {
      // never return NO_VALUE
      timeStamp--;
    }
    return timeStamp;
  }

  private static long getZipCrc(File archive) throws IOException {
    long computedValue = ZipUtil.getZipCrc(archive);
    if (computedValue == NO_VALUE) {
      // never return NO_VALUE
      computedValue--;
    }
    return computedValue;
  }

  private static List<File> performExtractions(File sourceApk, File dexDir) throws IOException {

    final String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;

    // Ensure that whatever deletions happen in prepareDexDir only happen if the zip that
    // contains a secondary dex file in there is not consistent with the latest apk.  Otherwise,
    // multi-process race conditions can cause a crash loop where one process deletes the zip
    // while another had created it.
    prepareDexDir(dexDir, extractedFilePrefix);

    List<File> files = null;

    return files;
  }

  /** This removes any files that do not have the correct prefix. */
  private static void prepareDexDir(File dexDir, final String extractedFilePrefix)
      throws IOException {
    dexDir.mkdir();
    if (!dexDir.isDirectory()) {
      throw new IOException("Failed to create dex directory " + dexDir.getPath());
    }

    // Clean possible old files
    FileFilter filter =
        new FileFilter() {

          @Override
          public boolean accept(File pathname) {
            return !pathname.getName().startsWith(extractedFilePrefix);
          }
        };
    File[] files = dexDir.listFiles(filter);
    if (files == null) {
      return;
    }
    for (File oldFile : files) {
      if (!oldFile.delete()) {
      } else {
      }
    }
  }

  /** Closes the given {@code Closeable}. Suppresses any IO exceptions. */
  private static void closeQuietly(Closeable closeable) {
    try {
      closeable.close();
    } catch (IOException e) {
    }
  }
}
