package nxm.sys.intr;

import nxm.sys.lib.Intrinsic;
import nxm.sys.lib.Shell;
import nxm.sys.lib.Stack;

/**
  Shows a Shell command history

  @author Jeff Schoen
*/
public class History extends Intrinsic {
  /** maximum number of commands to display */
  private int maxCommands = 64;

  /** instance of shell */
  private Shell shell;

  /** instance of history */
  private Stack history;

  /** Perform a case-sensitive comparison? */
  private boolean caseSensitive = false;

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

  /** Main process routine print out a history list of the available commands */
  @SuppressWarnings("deprecation")  // for M.terminal - since 3.7.1 for NXM-2813
  public int process () {
    caseSensitive = MA.getState("/CS", caseSensitive);
    String cmd = MA.getCS("CMD");
    int num = MA.getI("NUM");

    shell = M.terminal.getShell(); // since 3.3.1: check if terminal has a shell with history to use first (BUG 1758)
    if (shell == null) {
      shell = (Shell) M.registry.get("SHELL"); // fall-back to looking at REG.SHELL
    }
    history = shell.getHistory();

    matchCommands(cmd, num);

    rewind();

    return FINISH;
  }

  /** Print all instances of commands that match the parameters */
  private void matchCommands (String cmdAsEntered, int matchNum) {
    Stack answer = new Stack(maxCommands);

    Object peekobj = history.peek ( -1 );
    int cmdnum = 1;
    int matches = 0;
    String cmd = cmdAsEntered;
    if (!caseSensitive) cmd = cmd.toUpperCase();
    // cycle through the command history until it ends
    while ( ( peekobj != null ) && ( cmdnum <= maxCommands ) ) {

      String strAsEntered = (String) peekobj;
      String str = strAsEntered;
      if (!caseSensitive) str=str.toUpperCase();
      // check to see if we match the string (will match if it's empty)
      if ( str.startsWith (cmd) ) {
        matches++;

        // check to see if we have a number of matches to look for
        if ( (matchNum == 0) || (matches <= matchNum) ) {
          answer.push(" "+strAsEntered);
        }
      }

      peekobj = history.peek ( -1 );
      cmdnum++;
    }

    Object obj = answer.pop();
    while (obj != null) {
      M.println(obj.toString());  // since 3.7.1 using M.println instead of M.terminal.writeln to allow logging - NXM-1813
      obj = answer.pop();
    }
  }

  /** Rewinds the stack to it's initial position so up and down arrows work */
  private void rewind () {
    Object peekobj = history.peek ( 1 );

    // cycle through the command history until it ends
    while ( peekobj != null ) {
      peekobj = history.peek ( 1 );
    }
  }
}

