package nxm.sys.lib;

import java.io.File;
import java.util.HashMap;

import nxm.sys.inc.ProvisionalUseOnly;
import nxm.sys.inc.ShellParent;

/** A class to run under MATLAB.

    @author Jeff Schoen
    @since  NeXtMidas 3.7.0
*/
@ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
public class MatLab implements ShellParent {

  private Shell shell;
  private boolean opened;
  private Terminal terminal;

  /** default constructor */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public MatLab() {
    // set the shell privileges & define noexternal
    Shell.setPriv(Privileges.PRIV_ALL);
    System.setProperty("NOEXTERNAL", "TRUE");
  }

  /** MatLab constructor
   *
   *  @param nmroot NMROOT
   *  @param home   HOME
   *  @param nonat  NONATIVE
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public MatLab (String nmroot, String home, String nonat) {
    this();
    System.setProperty("NMROOT", nmroot+"/");
    System.setProperty("HOME", home+"/");
    System.setProperty("NONATIVE", nonat);
    opened = false;
  }

  /** open */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public void open () {
    String fname; File file;
    terminal = new MatLabTerminal();
    shell = new Shell(this);
    shell.open();
    // check for an nmstartup.mm file in the system directory
    fname = shell.M.io.getName("SYS", "CFG", "nmstartup", "mm");
    file = new File(fname);
    if (file.exists()) runCommand("%nmstartup,/MFN="+fname);
    // check for an nmstartup.mm file in the home directory
    fname = shell.M.io.getName("AUX", "HOME", "nmstartup", "mm");
    file = new File(fname);
    if (file.exists()) runCommand("%nmstartup,/MFN="+fname);
    opened = true;
  }

  /** check if is open
   *  @return true if opened
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public boolean isOpen () {
    return opened;
  }

  /** get NeXtMMidas Option Trees
   *  @return String array with NeXtMidas Option trees
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String[] getNmOpts () {
    // get the option trees in the path
    String path = (String) shell.M.results.get("OPT.PATH");
    // break apart option trees
    String[] out = path.split(",");

    String cur;
    int ind;

    for ( int m=0; m<out.length; m++ ) {
      cur = shell.M.io.name ("", "", "", out[m]);
      ind = cur.indexOf("/nxm/");
      // parse to 'nxm' if it exists
      out[m] = ( ind > 0 ) ? cur.substring(0, ind): cur;
    }
    return out;
  }

  /** get result
   *
   *  @param rn result name
   *  @return HasMap holding result
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public HashMap<String, String> getResult ( String rn ) {
    // get the result
    Object res = shell.M.results.get(rn);

    HashMap<String, String> out = new HashMap<>();
    if ( res instanceof Table ) {
      Table tbl = (Table) res;
      String[] keys = tbl.getKeys();
      for ( int m=0; m<keys.length; m++ ) {
        out.put(keys[m], tbl.get(keys[m]).toString());
      }
    }
    else {
      out.put(rn, res.toString());
    }
    return out;
  }

  /** run command
   *
   *  @param cmdline String with command to run
   *  @return status
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String runCommand (String cmdline) {
    Command cmd = Shell.runCommand (shell.M, cmdline, null, null);
    return cmd.getStatus();
  }

  /** close */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public void close () {
    opened = false;
  }

  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getNmRoot () {
    return Shell.getProperty("NMROOT");
  }

  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getHome () {
    return Shell.getProperty("HOME");
  }

  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public Terminal getTerminal () {
    return terminal;
  }

  /** Gets the current shell containing the Midas context
      @return current shell
   */
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public Shell getShell () {
    return shell;
  }

  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getNMS () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getAux () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getOpts () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getCWD () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getServer () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getTheme () { return null; }
  @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
  public String getStyle () { return null; }

  private static class MatLabTerminal extends Terminal {
    // don't know how to get terminal input yet - this stops it from hanging on input for now
    @ProvisionalUseOnly("Added in NeXtMidas 3.7.0")
    public String getInput (String prompt, String seed, int flags) {
      return (seed==null)? "":seed;
    }
  }

}
