package org.checkerframework.javacutil;

import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Options;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.processing.ProcessingEnvironment;
import org.checkerframework.checker.nullness.qual.Nullable;

/** This file contains basic utility functions. */
public class SystemUtil {

  /**
   * Returns the major JRE version.
   *
   * <p>This is different from the version passed to the compiler via --release; use {@link
   * #getReleaseValue(ProcessingEnvironment)} to get that version.
   *
   * <p>Extract the major version number from the "java.version" system property. Two possible
   * formats are considered. Up to Java 8, from a version string like `1.8.whatever`, this method
   * extracts 8. Since Java 9, from a version string like `11.0.1`, this method extracts 11.
   *
   * @return the major version number from "java.version"
   */
  public static int getJreVersion() {
    final String jreVersionStr = System.getProperty("java.version");

    final Pattern oldVersionPattern = Pattern.compile("^1\\.(\\d+)\\..*$");
    final Matcher oldVersionMatcher = oldVersionPattern.matcher(jreVersionStr);
    if (oldVersionMatcher.matches()) {
      String v = oldVersionMatcher.group(1);
      assert v != null : "@AssumeAssertion(nullness): inspection";
      return Integer.parseInt(v);
    }

    // See http://openjdk.java.net/jeps/223
    // We only care about the major version number.
    final Pattern newVersionPattern = Pattern.compile("^(\\d+).*$");
    final Matcher newVersionMatcher = newVersionPattern.matcher(jreVersionStr);
    if (newVersionMatcher.matches()) {
      String v = newVersionMatcher.group(1);
      assert v != null : "@AssumeAssertion(nullness): inspection";
      return Integer.parseInt(v);
    }

    // For Early Access version of the JDK
    final Pattern eaVersionPattern = Pattern.compile("^(\\d+)-ea$");
    final Matcher eaVersionMatcher = eaVersionPattern.matcher(jreVersionStr);
    if (eaVersionMatcher.matches()) {
      String v = eaVersionMatcher.group(1);
      assert v != null : "@AssumeAssertion(nullness): inspection";
      return Integer.parseInt(v);
    }

    throw new RuntimeException(
        "Could not determine version from property java.version=" + jreVersionStr);
  }

  /**
   * Returns the release value passed to the compiler or null if release was not passed.
   *
   * @param env the ProcessingEnvironment
   * @return the release value or null if none was passed
   */
  public static @Nullable String getReleaseValue(ProcessingEnvironment env) {
    Context ctx = ((JavacProcessingEnvironment) env).getContext();
    Options options = Options.instance(ctx);
    return options.get(Option.RELEASE);
  }

  /**
   * Returns the pathname to the tools.jar file, or null if it does not exist. Returns null on Java
   * 9 and later.
   *
   * @return the pathname to the tools.jar file, or null
   */
  public static @Nullable String getToolsJar() {

    if (getJreVersion() > 8) {
      return null;
    }

    String javaHome = System.getenv("JAVA_HOME");
    if (javaHome == null) {
      String javaHomeProperty = System.getProperty("java.home");
      if (javaHomeProperty.endsWith(File.separator + "jre")) {
        javaHome = javaHomeProperty.substring(javaHomeProperty.length() - 4);
      } else {
        // Could also determine the location of javac on the path...
        throw new Error("Can't infer Java home; java.home=" + javaHomeProperty);
      }
    }
    String toolsJarFilename = javaHome + File.separator + "lib" + File.separator + "tools.jar";
    if (!new File(toolsJarFilename).exists()) {
      throw new Error(
          String.format(
              "File does not exist: %s ; JAVA_HOME=%s ; java.home=%s",
              toolsJarFilename, javaHome, System.getProperty("java.home")));
    }
    return javaHome + File.separator + "lib" + File.separator + "tools.jar";
  }

  ///
  /// Array and collection methods
  ///

  /**
   * Returns a list that contains all the distinct elements of the two lists: that is, the union of
   * the two arguments.
   *
   * <p>For very short lists, this is likely more efficient than creating a set and converting back
   * to a list.
   *
   * @param <T> the type of the list elements
   * @param list1 a list
   * @param list2 a list
   * @return a list that contains all the distinct elements of the two lists
   */
  public static <T> List<T> union(List<T> list1, List<T> list2) {
    List<T> result = new ArrayList<>(list1.size() + list2.size());
    addWithoutDuplicates(result, list1);
    addWithoutDuplicates(result, list2);
    return result;
  }

  /**
   * Adds, to dest, all the elements of source that are not already in dest.
   *
   * <p>For very short lists, this is likely more efficient than creating a set and converting back
   * to a list.
   *
   * @param <T> the type of the list elements
   * @param dest a list to add to
   * @param source a list of elements to add
   */
  @SuppressWarnings("nullness:argument" // true positive:  `dest` might be incompatible with
  // null and `source` might contain null.
  )
  public static <T> void addWithoutDuplicates(List<T> dest, List<? extends T> source) {
    for (T elt : source) {
      if (!dest.contains(elt)) {
        dest.add(elt);
      }
    }
  }

  /**
   * Returns a list that contains all the elements that are in both lists: that is, the set
   * difference of the two arguments.
   *
   * <p>For very short lists, this is likely more efficient than creating a set and converting back
   * to a list.
   *
   * @param <T> the type of the list elements
   * @param list1 a list
   * @param list2 a list
   * @return a list that contains all the elements of {@code list1} that are not in {@code list2}
   */
  public static <T> List<T> intersection(List<? extends T> list1, List<? extends T> list2) {
    List<T> result = new ArrayList<>(list1);
    result.retainAll(list2);
    return result;
  }

  ///
  /// Deprecated methods
  ///

  /**
   * Return a list of Strings, one per line of the file.
   *
   * @param argFile argument file
   * @return a list of Strings, one per line of the file
   * @throws IOException when reading the argFile
   * @deprecated use Files.readAllLines
   */
  @Deprecated // 2021-03-10
  public static List<String> readFile(final File argFile) throws IOException {
    final BufferedReader br = new BufferedReader(new FileReader(argFile));
    String line;

    List<String> lines = new ArrayList<>();
    while ((line = br.readLine()) != null) {
      lines.add(line);
    }
    br.close();
    return lines;
  }

  /**
   * Like Thread.sleep, but does not throw any exceptions, so it is easier for clients to use.
   * Causes the currently executing thread to sleep (temporarily cease execution) for the specified
   * number of milliseconds.
   *
   * @param millis the length of time to sleep in milliseconds
   * @deprecated use SystemPlume.sleep
   */
  @Deprecated // 2021-03-10
  public static void sleep(long millis) {
    try {
      Thread.sleep(millis);
    } catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
    }
  }

  /**
   * Concatenates an element, an array, and an element.
   *
   * @param <T> the type of the array elements
   * @param firstElt the first element
   * @param array the array
   * @param lastElt the last elemeent
   * @return a new array containing first element, the array, and the last element, in that order
   * @deprecated use PlumeUtil.concat
   */
  @Deprecated // 2021-03-10
  @SuppressWarnings("unchecked")
  public static <T> T[] concatenate(T firstElt, T[] array, T lastElt) {
    @SuppressWarnings("nullness") // elements are not non-null yet, but will be by return stmt
    T[] result = Arrays.copyOf(array, array.length + 2);
    result[0] = firstElt;
    System.arraycopy(array, 0, result, 1, array.length);
    result[result.length - 1] = lastElt;
    return result;
  }

  /**
   * Return true if the system property is set to "true". Return false if the system property is not
   * set or is set to "false". Otherwise, errs.
   *
   * @param key system property to check
   * @return true if the system property is set to "true". Return false if the system property is
   *     not set or is set to "false". Otherwise, errs.
   * @deprecated use UtilPlume.getBooleanSystemProperty
   */
  @Deprecated // 2021-03-28
  public static boolean getBooleanSystemProperty(String key) {
    return Boolean.parseBoolean(System.getProperty(key, "false"));
  }

  /**
   * Return its boolean value if the system property is set. Return defaultValue if the system
   * property is not set. Errs if the system property is set to a non-boolean value.
   *
   * @param key system property to check
   * @param defaultValue value to use if the property is not set
   * @return the boolean value of {@code key} or {@code defaultValue} if {@code key} is not set
   * @deprecated use UtilPlume.getBooleanSystemProperty
   */
  @Deprecated // 2021-03-28
  public static boolean getBooleanSystemProperty(String key, boolean defaultValue) {
    String value = System.getProperty(key);
    if (value == null) {
      return defaultValue;
    }
    if (value.equals("true")) {
      return true;
    }
    if (value.equals("false")) {
      return false;
    }
    throw new Error(
        String.format(
            "Value for system property %s should be boolean, but is \"%s\".", key, value));
  }

  /**
   * Concatenates two arrays. Can be invoked varargs-style.
   *
   * @param <T> the type of the array elements
   * @param array1 the first array
   * @param array2 the second array
   * @return a new array containing the contents of the given arrays, in order
   * @deprecated use StringsPlume.concatenate
   */
  @Deprecated // 2021-03-28
  @SuppressWarnings("unchecked")
  public static <T> T[] concatenate(T[] array1, T... array2) {
    @SuppressWarnings("nullness") // elements are not non-null yet, but will be by return stmt
    T[] result = Arrays.copyOf(array1, array1.length + array2.length);
    System.arraycopy(array2, 0, result, array1.length, array2.length);
    return result;
  }

  /**
   * Given an expected number of elements, returns the capacity that should be passed to a HashMap
   * or HashSet constructor, so that the set or map will not resize.
   *
   * @param numElements the maximum expected number of elements in the map or set
   * @return the initial capacity to pass to a HashMap or HashSet constructor
   * @deprecated use CollectionsPlume.mapCapacity
   */
  @Deprecated // 2021-05-05
  public static int mapCapacity(int numElements) {
    // Equivalent to: (int) (numElements / 0.75) + 1
    // where 0.75 is the default load factor.
    return (numElements * 4 / 3) + 1;
  }

  /**
   * Given an expected number of elements, returns the capacity that should be passed to a HashMap
   * or HashSet constructor, so that the set or map will not resize.
   *
   * @param c a collection whose size is the maximum expected number of elements in the map or set
   * @return the initial capacity to pass to a HashMap or HashSet constructor
   * @deprecated use CollectionsPlume.mapCapacity
   */
  @Deprecated // 2021-05-05
  public static int mapCapacity(Collection<?> c) {
    return mapCapacity(c.size());
  }

  /**
   * Given an expected number of elements, returns the capacity that should be passed to a HashMap
   * or HashSet constructor, so that the set or map will not resize.
   *
   * @param m a map whose size is the maximum expected number of elements in the map or set
   * @return the initial capacity to pass to a HashMap or HashSet constructor
   * @deprecated use CollectionsPlume.mapCapacity
   */
  @Deprecated // 2021-05-05
  public static int mapCapacity(Map<?, ?> m) {
    return mapCapacity(m.size());
  }
}
