package nxm.sys.intr;

import nxm.sys.lib.Args;
import nxm.sys.lib.Command;
import nxm.sys.lib.Intrinsic;
import nxm.sys.lib.Macro;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Shell;
import nxm.sys.lib.Terminal;
import nxm.sys.lib.TextFile;

/**
  Performs creation, translation, and listing of macros for debug.

  @author Jeff Schoen
*/
public class Macrofunc extends Intrinsic {

  private String func,name;
  private Macro macro;
  private int index1,index2,wind;

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

  @SuppressWarnings("deprecation")  // for M.terminal - since 3.7.1 for NXM-2813
  public int process() {

    name = MA.getU("NAME");
    func = MA.getU("FUNC");
    wind = MA.getL("WIND");

    if (func.equals("ENTER")) {  // Enter the macro from the command line
      if (name == null || name.length() <= 0) {
        M.error("Need to give a macro name (like mymacro) to generate new macro");
      } else {
        // Make sure the name starts with a %, i.e is a user macro.
        String userMacro = name; if (!name.startsWith("%")) userMacro = "%"+userMacro;
        enterMacroText (M, userMacro,"startmacro","endmacro");
        Shell.runCommand(M,userMacro);
      }
    } else if (func.equals("LIST")) {  // List the given macro or current one in which this is running.
      if (M.macro != null && (name == null || name.equals("")) ) {
        macro = M.macro;
        index1 = Math.max(1,macro.nextIndex-wind);
        index2 = Math.min(macro.lastIndex,macro.nextIndex+wind);
      } else {
        Args targs = Shell.parseCommand(M,name);
        Command command = Shell.loadCommand(M,targs);
        if (command instanceof Macro) {
          macro = (Macro)command;
          macro.loadText();
        } else {
          M.error ("Unable to load macro: '"+name+"'");
          return FINISH;
        }
        index1 = 1;
        index2 = macro.lastIndex;
      }

      M.more(Terminal.INIT);  // since 3.7.1 using M.more instead of M.terminal.more - NXM-1813
      for (int i=index1; i<index2; i++) {
        String line = (i==macro.nextIndex)? "*":" ";
        M.more( line+i+"-> "+macro.lines[i].toString() );
      }
      M.more(Terminal.EXIT);
    }

    return FINISH;
  }

  /** Enter macro text
   *  @param M    Midas context
   *  @param name Macro name
   *  @param seed Macro seed (i.e. "startmacro")
   *  @param term Macro term (i.e. "endmacro")
   */
  public static void enterMacroText (Midas M, String name, String seed, String term) {
    String fname = Macro.getFileName (M,name,"USER");
    writeMacroText(M, fname, seed, term);
  }

  /** Intrinsic macro text (ex: DO, FOREACH, WHILE)
   *  @param M    Midas context
   *  @param name Macro name
   *  @param seed Macro seed (i.e. "foreach x INTAB OPT")
   *  @param term Macro term (i.e. "endfor")
   *  @return the percent command, including full path
   */
  static String enterIntrMacroText (Midas M, String name, String seed, String term) {
    String aux = (Shell.getAuxPath("HOMEPATH").startsWith("classpath:")) ?
        "WRITE" : "HOMEPATH";
    String fname = M.io.name(aux, name.substring(1), "MM", "AUX");
    writeMacroText(M, fname, seed, term);
    return "%"+fname;
  }

  /** ,acro text (ex: DO, FOREACH, WHILE)
   *  @param M    Midas context
   *  @param fname Macro file name (in HOMEPATH if macrofunc, WRITE AUX if Intrinsic)
   *  @param seed Macro seed
   *  @param term Macro term
   */
  private static void writeMacroText (Midas M, String fname, String seed, String term) {
    TextFile tf = new TextFile (M,fname);

    tf.open(TextFile.OUTPUT|TextFile.FORCEABORT);
    String line = "OK";
    tf.writeln("startmacro /sharemask=+RESULTS \n");  // sharemask added for Bug 2454
    tf.writeln("  global;sys/readall\n"); // Bug 1801 allows macro transparent READ access to NeXtMidas shell results
    if (!seed.startsWith("startmacro")) { tf.writeln("  "+seed); }
    Shell shell = ((M.getTerminal()!=null) && (M.getTerminal().getShell()!=null)) ?
        M.getTerminal().getShell() : Shell.getCurrent();
    while (line.length()>0) {
      line = shell.getNextCommand(">>> ","");
      if (line.length()>0) {
        if (line.startsWith(term)) { tf.writeln("  "+line);   }
        else                       { tf.writeln("    "+line); }
      }
      if (line.startsWith(term)) break;
      seed = "";
    }
    if (line.length()==0) {
      if (term.startsWith("endmacro")) { tf.writeln(term); }
      else { tf.writeln("  "+term+"\n");}
      M.println(">>> "+term);  // since 3.7.1 using M.println instead of M.terminal.writeln to allow logging - NXM-1813
    }
    if (!term.startsWith("endmacro")) { tf.writeln("endmacro"); }
    tf.close();
  }

}
