package nxm.sys.intr;

import nxm.sys.lib.Args;
import nxm.sys.lib.Command;
import nxm.sys.lib.Foreign;
import nxm.sys.lib.Intrinsic;
import nxm.sys.lib.Macro;
import nxm.sys.lib.Shell;

/**
  Edit a command in the dictionary or user macro.

  @author Jeff Schoen / Jay Hallam
*/
public class Edit extends Intrinsic {

  /** default constructor */
  public Edit () {}

  public int process() {

    String name = MA.getCS("NAME");
    String area = MA.getU("AREA");
    String option = MA.getU("OPT","SYS");
    boolean build = !MA.getState("/NB");
    String editor = MR.getString("ENV.EDITOR");
    String ext = "java";

    int ip = name.lastIndexOf('.');
    if (ip>=0) {
      ext = name.substring(ip+1);
      name = name.substring(0,ip);
    }

    /* If the user enters the AREA we do not want to find the command
    in the dictionary, just want to build the path */
    Args targs = null;
    if (area == null || area.length() <= 0) {
      // Get the full path from the command name
      targs = Shell.parseCommand(M,name);
      option = targs.option.toLowerCase();
    }

    if (targs == null) {
      String inputName = M.io.name (area, name, ext, option); // Input file
      // Search for file if it does not exist as entered
      String fname = findCloseMatch(inputName, option, area, name, ext);
      if (fname == null) {
        build = false;
        M.warning("Could not find file match for '"+inputName+"'");
      } else {
        if (ext.equals("exp")) build = false;
        Foreign.runInternal (M,editor+" "+fname);
      }
    }
    else if (targs.support=='M') {
      String fname = Macro.getFileName(M,name,option);
      String fnamet = fname.substring(0,fname.length()-2)+"txt";
      if (M.io.fexists(fname));
      else if (M.io.fexists(fnamet)) fname=fnamet;
      else M.error("File for macro="+targs.name+" not found");
      Foreign.runInternal (M,editor+" "+fname);
      Command command = Shell.loadCommand(M,targs);
      ((Macro)command).loadText(); // try translation
      build = false;
    }
    else if (targs.support=='P') {
      String fname = targs.name.toLowerCase();
      fname = M.io.getName(option,"prim",fname,ext);
      Foreign.runInternal (M,editor+" "+fname);
    }
    else if (targs.support=='H') {
      String fname = targs.name.toLowerCase();
      if (ip<0) ext = "for";
      fname = M.io.getName(option,"host",fname,ext);
      Foreign.runInternal (M,editor+" "+fname);
    }
    else if (targs.support=='I') {
      String fname = targs.name.substring(0,1)+targs.name.substring(1).toLowerCase();
      fname = M.io.getName(option,"intr",fname,ext);
      Foreign.runInternal (M,editor+" "+fname);
    }
    else {
      build = false;
      M.warning("Could not find command "+name);
    }

    if (build) Shell.runCommand(M,"BLD,"+name+","+area+","+option);

    if (area.equals("LIBM") && (name.equals("operators") || name.equals("generate"))) {
      Shell.runCommand(M,"GENERATE,OPER,ALL");
      Shell.runCommand(M,"BLD,ALL,LIBM");
    }

    return FINISH;
  }

  /** Find a close match(es) for a file name */
  private String findCloseMatch (String inputName, String option, String area,
                                 String name, String ext) {
    String outName = null;

    // Search for file if it does not exist as entered
    if (new java.io.File(inputName).exists()) {
      outName = inputName;
    } else {
      // Could not find file as entered, use first match
      String path = M.io.name(area,"","",option);
      String[] files = M.io.listFiles (path, name, ext );

      if (files.length > 0) {outName = path+files[0];}

      // If we found more than 1 match, alert the user
      if (files.length > 1) {
        M.warning("Found "+files.length+" matching files. Using first = "+files[0]);
        for (int i=0; i < files.length; i++) {
          M.warning("\tFile "+i+" = "+files[i]);
        }
      }
    }
    return outName;
  }

}
