// 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.io.UncheckedIOException;
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 = StringUtils.toLowerCase(path.getFileName().toString());
    return name.endsWith(DEX_EXTENSION);
  }

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

  public static boolean isClassFile(String path) {
    String name = StringUtils.toLowerCase(path);
    // 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 = StringUtils.toLowerCase(path.getFileName().toString());
    return name.endsWith(JAR_EXTENSION);
  }

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

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

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

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

  public static boolean isArchive(Path path) {
    String name = StringUtils.toLowerCase(path.getFileName().toString());
    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 byte[] uncheckedReadAllBytes(Path file) {
    try {
      return Files.readAllBytes(file);
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

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

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

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

  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 = StringUtils.toLowerCase(file.getFileName().toString());
    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('/', '\\');
    }
  }

  @SuppressWarnings("ReferenceEquality")
  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());
  }
}
