package nxm.sys.libxm;

import nxm.sys.inc.InternalUseOnly;
import nxm.sys.inc.ShellParent;
import nxm.sys.lib.OptionTree;
import nxm.sys.lib.Shell;
import nxm.sys.lib.XMValue;

/** An extension of the normal NeXtMidas {@link Shell} class that overrides a few minor things so
    they are compatible with X-Midas.
    <span style="color:red">Do NOT use this class directly, this class
    is for use by the SYS option tree ONLY and is subject to change without notice!</span>
    @author Pete Perrino, J. Czechowski IV
*/
@InternalUseOnly
public class XmShell extends Shell {
  /** Creates a new instance.
      @param parent The shell parent to use.
   */
  public XmShell(ShellParent parent) {
    super(parent);
    noExternalCmds = true; // Do not allow os commands to exit shell.
  }

  /** Boot the XmShell. Sets up the NeXtMidas path and creates the AUX and XM results. */
  public void boot() {
    // Setting of path must come before any use of XMValueNative
    super.boot();
    setupNXMPath();

    // Set default XMValue implementation to point to native X-Midas
    if (XMValueNative.isSupported()) {
      XMValue.setDefaultBackend(XMValueNative.class);
    }

    // Set AUX and XM results
    M.results.put("AUX", new XmAuxTable());
    if (XMValueNative.isSupported()) {
      M.results.put("XM", new XMValueNative.ResultTable());  // <-- X-Midas 4.6 and later
    }
    else {
      M.results.put("XM", new XmResultTable());              // <-- X-Midas 4.4 and earlier
    }
  }

  /** Setup the path definitions for all of the option trees defined in X-Midas.
      <pre>This takes care of any quirky NeXtMidasisms like:
        (1) Option trees already in $NMROOT/nxm/
        (2) Making sure that an NXM option which points to the NeXtMidas SYS is not added.
      </pre>
  */
  private void setupNXMPath() {
    String startPath = parent.getOpts();
    if (startPath == null) return;
    String[] opts = startPath.split(",");
    String path = null;
    for (int i = 0; i < opts.length; i++) {
      if (opts[i].equals("SYS")) {
        // Do not override the SYS option definition
      } else if ((opts[i] != null) && (opts[i].trim().length() > 0)) {
        path = ((XmShellParent)parent).getOptionPath(opts[i]);

        if (path == null) {
          M.warning("Can not access $XMAREA_"+opts[i].toUpperCase());
        } else {
          OptionTree.defineOptionTree(M, opts[i], path);
        }
      }
    }
  }

  /** Dispatches an X-Midas command to be run.
      @param cmd  Command line to spawn in parent or subshell.
      @param flag Mode flag bitmask (see X-Midas docs for M$DISPATCH).
      @param mask Subshell shared section mask (see X-Midas docs for M$DISPATCH).
   */
  public static void dispatch(String cmd, int flag, int mask) {
    XMidas.dispatch(cmd, flag, mask);
  }
}
