
// PyUtils.java
// Andrew Davison, ad@coe.psu.ac.th, July 2023

/* Helper functions for using Python from Java.
   Includes:
      * python code execution
      * int array manipulation
      * use of temp files
      * text and image file I/O
*/


import java.io.*;
import java.util.*;
import java.nio.file.*;
import java.util.stream.*;

import javax.swing.*;
import java.awt.image.*;
import javax.imageio.*;



public class PyUtils
{
  
  public static int exec(String... cmdStr)
  // evaluate command, returning exit value
  {
    String[] cmdToks;
    if (cmdStr.length == 1)    
      // input is one string, which may need tokenizing
      cmdToks = cmdStr[0].split("\\s+");
    else
      cmdToks = cmdStr;
    // System.out.println(Arrays.toString(cmdToks));

    int exitValue = 1;    // assume the worst
    ProcessBuilder pb = new ProcessBuilder(cmdToks);
    pb.inheritIO();
          //  sets standard I/O to be the same as for Java

    Process p = null;
    try {
      p = pb.start();
      exitValue = p.waitFor();
    }
    catch(Exception e) {  
      System.out.println(e);  
    }  
    finally {
      if (p != null)
        p.destroy(); 
    }
    return exitValue;
  }  // end of exec()



  // ---------------- array manipulation --------------------
  // only integer arrays supported

  public static int[][] reshapeInt2D(int[] arr, int[] dims)
  {
     if (dims.length != 2) {
       System.out.println("Dimensions are not 2D");
       return null;
     }
     else
       return reshapeInt2D(arr, dims[0], dims[1]);
  }


  public static int[][] reshapeInt2D(int[] arr, int numRows, int numCols)
  {
    if ((numRows <= 0) || (numCols <= 0)) {
      System.out.println("New dimensions must be positive");
      return null;
    }

    int[][] nArr = new int[numRows][numCols];

    int nLen = numRows * numCols;
    int max = (nLen > arr.length) ? arr.length : nLen;

    int i = 0;
    for (int r=0; r < numRows; r++)
      for (int c = 0; c < numCols; c++)
         if (r*c < max) {
           nArr[r][c] = arr[i];
           i++;
         }

    return nArr;
  }  // end of reshapeInt2D()


  public static void printInt2D(int[][] arr)
  {
    int numRows = arr.length;
    if (numRows == 1)
      System.out.println("[" + Arrays.toString(arr[0]) + "]");
    else {
      System.out.println("[" + Arrays.toString(arr[0]));
      for (int r=1; r < numRows-1; r++) 
        System.out.println(" " + Arrays.toString(arr[r]));
      System.out.println(" " + Arrays.toString(arr[numRows-1]) + "]");
    }
  }  // end of printInt2D()



  // ------------------- temp files -------------------------


  public static String writeToTemp(String[] lines)
  // write lines of text to a temporay file, and return the
  // file name
  {
	try {
      File f = File.createTempFile("temp", ".txt");
      f.deleteOnExit();   // Delete when JVM exits
      String path = f.getAbsolutePath();

      BufferedWriter bw = new BufferedWriter(new FileWriter(f));
      for(String line : lines) {
        bw.write(line);
        bw.newLine();
      }
      bw.close();

      return path;
	}
	catch (IOException e) 
    {  System.out.println("Could not create temp file");  }

    return null;
  }  // end of writeToTemp()



  public static String makeTemp(String ext)
  // create a temporary file with the given extension,
  // and return the file name
  {
    if (!ext.startsWith("."))
      ext = "." + ext;

	try {
      File f = File.createTempFile("temp", ext);
      f.deleteOnExit();   // Delete when JVM exits
      return f.getAbsolutePath();
	}
	catch (IOException e) 
    {  System.out.println("Could not create temp file with extension " + ext);  }
    return null;
  }  // end of writeToTemp()



  // ----------------- file I/O ------------------------------


  public static List<String> readLines(String fnm)
  {
    try (BufferedReader br = new BufferedReader(
                                  new FileReader(fnm))) {
      return br.lines().collect(Collectors.toList());
    }
    catch(Exception e) {
      System.out.println("Cannot read " + fnm + "\n");
      return null;
    }
  } /* readLines */


  public static String readString(String fnm)
  {
    try (BufferedReader br = new BufferedReader(
                                  new FileReader(fnm))) {
      return br.lines().collect(
         Collectors.joining(System.lineSeparator()));
    }
    catch(Exception e) {
      System.out.println("Cannot read " + fnm + "\n");
      return null;
    }
  } /* readString */



  public static BufferedImage loadImage(String fnm)
  {
    try {
      return ImageIO.read(new File(fnm));
    }
    catch(Exception e) {
      System.out.println("Cannot load " + fnm + "\n");
      return null;
    }
  }  // end of loadImage()



  public static void saveImage(BufferedImage im, String fnm)
  // save image in fnm
  {
    try {
      ImageIO.write(im, "png", new File(fnm));
      System.out.println("Saved image to " + fnm);
    } 
    catch (IOException e) {
      System.out.println("Could not save image to " + fnm);
    }
  }  // end of saveImage()



  public static double getDouble(String s)
  { 
    double num = 0;
    try {
      num = Double.parseDouble(s);
    }
    catch (NumberFormatException ex){ 
      System.out.println("Incorrect format for double " + s); 
    }
    return num;
  }  // end of getDouble()


  public static int getInt(String s)
  { 
    int num = 0;
    try {
      num = Integer.parseInt(s);
    }
    catch (NumberFormatException ex){ 
      System.out.println("Incorrect format for int " + s); 
    }
    return num;
  }  // end of getInt()



  public static String stripExt(String fnm)
  {
    int dotPos = fnm.lastIndexOf('.');
    if (dotPos == -1)
      return fnm;
    else
      return fnm.substring(0, dotPos);
  }


  public static String getName(String fnm)
  // remove path and extension from filename
  {
    Path p = Paths.get(fnm);
    String fileName = p.getFileName().toString();
    return stripExt(fileName);
  }  // end of getName()

}  // end of PyUtils class