// 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 com.android.tools.r8.utils;

import com.android.tools.r8.ByteDataView;
import com.google.common.io.Closer;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipFile;

public class FileUtils {

  public static final String AAR_EXTENSION = ".aar";
  public static final String APK_EXTENSION = ".apk";
  public static final String CLASS_EXTENSION = ".class";
  public static final String DEX_EXTENSION = ".dex";
  public static final String VDEX_EXTENSION = ".vdex";
  public static final String JAR_EXTENSION = ".jar";
  public static final String ZIP_EXTENSION = ".zip";
  public static final String JAVA_EXTENSION = ".java";
  public static final String KT_EXTENSION = ".kt";
  public static final String MODULE_INFO_CLASS = "module-info.class";
  public static final String MODULES_PREFIX = "/modules";
  public static final String GLOBAL_SYNTHETIC_EXTENSION = ".global";

  public static final boolean isAndroid =
      System.getProperty("java.vm.name").equalsIgnoreCase("Dalvik");

  public static boolean isDexFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(DEX_EXTENSION);
  }

  public static boolean isVDexFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(VDEX_EXTENSION);
  }

  public static boolean isClassFile(String path) {
    String name = path.toLowerCase();
    // Android does not support Java 9 module, thus skip module-info.
    if (name.equals(MODULE_INFO_CLASS)) {
      return false;
    }
    return name.endsWith(CLASS_EXTENSION);
  }

  public static boolean isClassFile(Path path) {
    return isClassFile(path.getFileName().toString());
  }

  public static boolean isJarFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(JAR_EXTENSION);
  }

  public static boolean isZipFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(ZIP_EXTENSION);
  }

  public static boolean isApkFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(APK_EXTENSION);
  }

  public static boolean isAarFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(AAR_EXTENSION);
  }

  public static boolean isJavaFile(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(JAVA_EXTENSION);
  }

  public static boolean isArchive(Path path) {
    String name = path.getFileName().toString().toLowerCase();
    return name.endsWith(APK_EXTENSION)
        || name.endsWith(JAR_EXTENSION)
        || name.endsWith(ZIP_EXTENSION)
        || name.endsWith(AAR_EXTENSION);
  }

  public static String readTextFile(Path file, Charset charset) throws IOException {
    return new String(Files.readAllBytes(file), charset);
  }

  public static List<String> readAllLines(Path file) throws IOException {
    return Files.readAllLines(file);
  }

  public static void writeTextFile(Path file, List<String> lines) throws IOException {
    Files.write(file, lines);
  }

  public static void writeTextFile(Path file, String... lines) throws IOException {
    Files.write(file, Arrays.asList(lines));
  }

  public static Path validateOutputFile(Path path, Reporter reporter) {
    if (path != null) {
      boolean isJarOrZip = isZipFile(path) || isJarFile(path);
      if (!isJarOrZip && !(Files.exists(path) && Files.isDirectory(path))) {
        reporter.error(new StringDiagnostic(
            "Invalid output: "
                + path
                + "\nOutput must be a .zip or .jar archive or an existing directory"));
      }
    }
    return path;
  }

  public static OutputStream openPath(
      Closer closer,
      Path file,
      OpenOption... openOptions)
      throws IOException {
    assert file != null;
    return openPathWithDefault(closer, file, null, openOptions);
  }

  public static OutputStream openPathWithDefault(
      Closer closer,
      Path file,
      OutputStream defaultOutput,
      OpenOption... openOptions)
      throws IOException {
    OutputStream mapOut;
    if (file == null) {
      assert defaultOutput != null;
      mapOut = defaultOutput;
    } else {
      mapOut = Files.newOutputStream(file, openOptions);
      closer.register(mapOut);
    }
    return mapOut;
  }

  public static boolean isClassesDexFile(Path file) {
    String name = file.getFileName().toString().toLowerCase();
    if (!name.startsWith("classes") || !name.endsWith(DEX_EXTENSION)) {
      return false;
    }
    String numeral = name.substring("classes".length(), name.length() - DEX_EXTENSION.length());
    if (numeral.isEmpty()) {
      return true;
    }
    char c0 = numeral.charAt(0);
    if (numeral.length() == 1) {
      return '2' <= c0 && c0 <= '9';
    }
    if (c0 < '1' || '9' < c0) {
      return false;
    }
    for (int i = 1; i < numeral.length(); i++) {
      char c = numeral.charAt(i);
      if (c < '0' || '9' < c) {
        return false;
      }
    }
    return true;
  }

  public static void writeToFile(Path output, OutputStream defValue, byte[] contents)
      throws IOException {
    writeToFile(output, defValue, ByteDataView.of(contents));
  }

  public static void writeToFile(Path output, OutputStream defValue, ByteDataView contents)
      throws IOException {
    try (Closer closer = Closer.create()) {
      OutputStream outputStream =
          openPathWithDefault(
              closer,
              output,
              defValue,
              StandardOpenOption.CREATE,
              StandardOpenOption.TRUNCATE_EXISTING,
              StandardOpenOption.WRITE);
      outputStream.write(contents.getBuffer(), contents.getOffset(), contents.getLength());
    }
  }

  public static String withNativeFileSeparators(String path) {
    char fileSeparator = File.separatorChar;
    if (fileSeparator == '/') {
      return path.replace('\\', '/');
    } else {
      assert fileSeparator == '\\';
      return path.replace('/', '\\');
    }
  }

  public static ZipFile createZipFile(File file, Charset charset) throws IOException {
    if (!isAndroid) {
      return new ZipFile(file, charset);
    }
    // On Android pre-26 we cannot use the constructor ZipFile(file, charset).
    // By default Android use UTF_8 as the charset, so we can use the default constructor.
    if (Charset.defaultCharset() == StandardCharsets.UTF_8) {
      return new ZipFile(file);
    }
    // If the Android runtime is started with a different default charset, the default constructor
    // won't work. It is possible to support this case if we read/write the ZipFile not with it's
    // own Input/OutputStream, but an external one which one can define on a different Charset than
    // default. We do not support this at the moment since R8 on dex is used only in tests, and
    // UTF_8 is the default charset used in tests.
    throw new RuntimeException(
        "R8 can run on dex only with UTF_8 as the default charset, but the charset used is "
            + Charset.defaultCharset());
  }
}
