
// SpaceUtils.java
// Andrew Davison, ad@coe.psu.ac.th, May 2023

/* Various functions, grouped into:
     * parsing
     * IO
     * Threads
     * arrays

  Usage:
    > compile.bat SpaceUtils.java
*/

import java.io.*;
import java.util.*;


public class SpaceUtils
{
  private static final String[] IGNORED_THREADS = 
        { "DestroyJavaVM", "AWT-EventQueue-0", 
          "AWT-Shutdown", "main", "SpaceViewer"  };


  // ---------------- parsing -------------------

  public static int parseInt(String s)
  {
    if (s == null)
      return 0;
    try {
      return Integer.parseInt(s);
    }
    catch (NumberFormatException ex) { 
      System.out.println(s + " could not be parsed as an int; using 0");
      return 0;
    }
  }  // end of parseInt()


  public static long parseLong(String s)
  {
    if (s == null)
      return 0;
    try {
      return Long.parseLong(s);
    }
    catch (NumberFormatException ex) { 
      System.out.println(s + " could not be parsed as a long; using 0");
      return 0;
    }
  }  // end of parseLong()



  public static double parseDouble(String s)
  { 
    if (s == null)
      return 0;
    try {
      return Double.parseDouble(s);
    }
    catch (NumberFormatException ex){ 
      System.out.println(s + " could not be parsed as a double; using 0");
      return 0;
    }
  }  // end of parseDouble()


  // ------------------ IO ------------------------


  public static String spaces(int n)
  // generate a string of n spaces
  {
    if (n <= 0)
      return "";
    else
      return String.format("%1$"+n+"s", "");
  }


  public static void pause(int ms)
  {
    if (ms <= 0)
      return;
    try {
      Thread.sleep(ms);
    }
    catch(InterruptedException ex) { }
  }  // end of pause()


  public static void waitEnter() 
  {
    Console c = System.console();
    if (c != null) {
      c.format("Press <enter> to continue...\n");
      c.readLine();
    }
  }


  // ------------------- Threads --------------


  public static void waitTerminated(Thread... threads) 
  {
    for (Thread t : threads) {
      try {
        t.join();
      }
      catch (InterruptedException e)
      {  System.out.println(e);  }
    }
    System.out.println("All threads have terminated");
  }  // end of waitTerminated()



  public static ArrayList<Pair<String,String>> listThreads()
  {
    ArrayList<Pair<String,String>> infoList = new ArrayList<>();

    Set<Thread> threads = Thread.getAllStackTraces().keySet();
    for (Thread t : threads) {
      if (isNamedUserThread(t)) {
        // System.out.println("\"" + t.getName() + "\"");
        infoList.add( new Pair<String,String>(t.getName(), 
                                      t.getState().toString()) );
      }
    }
    return infoList;
  }  // end of listThreads()


  public static boolean isNamedUserThread(Thread t)
  /* check if a thread name indicates that the thread is a
     system thread or is unnamed because it has a
     default name (such as "Thread-0")
  */
  {
    if (t.isDaemon())
      return false;

    for (int i=0; i < IGNORED_THREADS.length; i++)
      if (t.getName().equals(IGNORED_THREADS[i]))
        return false;

    if (t.getName().startsWith("Thread-"))   // unnamed user threads
      return false;

    if (t.getName().startsWith("pool-"))   // unnamed thread pools
      return false;

    return true;
  }  // end of isNamedUserThread()


  // ------------------ arrays --------------------


  public static int[][] randArr(int size, 
                 int min, int max, Random r)
  /* generate a size x size 2D int array with random
     values between min and max
  */
  {
    int[][] arr = new int[size][size];
    for (int row = 0; row < size; row++)
      for (int col = 0; col < size; col++)
        arr[row][col] = (int) r.nextInt((max - min) + 1) + min;
    return arr;
  }  // end of randArr()


  public static void printArr(int arr[][])
  {
    for (int i = 0; i < arr.length; i++) {
      for (int j = 0; j < arr[i].length; j++)
        System.out.printf("%3d ", arr[i][j]);
      System.out.println();
    }
    System.out.println();
  }  // end of printArr()


  public static int[] getColumn(int[][] arr, int index)
  // extract the index column of values from the 2D int array
  {
    int[] column = new int[arr[0].length];
    for(int i=0; i < column.length; i++)
       column[i] = arr[i][index];
    return column;
  }  // end of getColumn()


  public static int[][] cols2Arr(int[][] cols)
  // convert an array of columns into a 2D int array
  {
    int size = cols.length;
    int[][] arr = new int[size][size];
    for (int row = 0; row < size; row++)
      for (int col = 0; col < size; col++)
        arr[row][col] = cols[col][row];
    return arr;
  }  // end of cols2Arr()

}  // end of SpaceUtils class