package nxm.sys.prim;

import nxm.sys.inc.Installation;
import nxm.sys.lib.Message;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Shell;
import nxm.sys.lib.Terminal;
import nxm.sys.libg.GPrimitive;
import nxm.sys.libg.GTerminal;
import nxm.sys.libg.MJText;
import nxm.sys.libg.MWText;

/**
  A class to run the Midas shell from a Graphical User Interface.

  @author Jeff Schoen
*/
public class shellgui extends GPrimitive {

  /** Exit options mask for /EXIT= switch. */
  public static final String exitList = "COMMAND,MENU,MESSAGE,WINDOW";
  /** Close shellgui by sending an exit command */
  public static final int EXIT_COMMAND=0x1;
  /** Close shellgui by using the right-click pop-up menu */
  public static final int EXIT_MENU=0x2;
  /** Close shellgui by sending an exit message to the shellgui */
  public static final int EXIT_MESSAGE=0x4;
  /** Close shellgui by clicking the 'X' at the top-right corner of the window */
  public static final int EXIT_WINDOW=0x8;
  /** Close shellgui by either command, menu, message, or window */
  public static final int EXIT_ALL=0xF;

  /** Shell driving this SHELLGUI terminal */
  public Shell shell;
  /** Terminal driving the graphical text window */
  public GTerminal terminal;

  /** The parent terminal to back this terminal with */
  private Terminal saveterm;
  /** Is the shell is "attached" to the shell it was run from. */
  private boolean  attach;
  /** User specified exit options. See {@link #exitList} for mask options. */
  private int exit;
  private boolean exiting;
  /** Text area (window) for the terminal input/output */
  private MWText mwtext;

  /** deafult constructor */
  public shellgui () {}

  @SuppressWarnings("deprecation")  // for M.terminal - since 3.7.1 for NXM-2813
  public int open () {
    int lines  = MA.getL("/LINES",2000); // BUG 1830: to help with scroll issues
    int rows   = MA.getL("/ROWS",   30);
    int cols   = MA.getL("/COLS",  100); // BUG 1830: 80 normally cause output to wrap via "+"
    int fontsz = MA.getL("/FONTSZ", 12);
    int flags  = MJText.TEXT | MJText.BACKL | MJText.FIFO | MJText.INPUT | MJText.WRAP | MJText.COLOR | MJText.SHELLGUI;

    boolean addPlus = MA.getState("/ADDPLUS", true);  // BUG 1563: Give users ability to turn OFF
    if (addPlus) flags |= MJText.ADDPLUS;             //   plus sign at the end of a wrapped line

    attach = MA.getState("/ATTACH",false);
    // Can support only one attached SHELLGUI - since 3.7.1 for NXM-2872, ABORT if attempting to attach second shellgui
    if ((M.terminal != null) && (M.macro != null) &&
      (M.terminal.getShell() != M.macro.MT.getShell()) && attach) {
      Shell.runCommand(M,"POPUP,,OK,ERROR:Not_allowed_to_have_two_attached_SHELLGUIs,ERR");
      return ABORT;
    }

    MW = mwtext = new MWText("GShell",lines,rows,cols,fontsz,flags,this);
    MW.open();

    // The terminal to drive the text window
    terminal = new GTerminal(M,mwtext);
    saveterm = M.terminal;

    attach = MA.getState("/ATTACH",false);

    // The shell to drive the terminal
    shell = new Shell(M, attach);
    terminal.setShell(shell); // since 3.3.1: set Shell for history on terminal (BUG 1758)

    if (attach) {
      if (M.macro==null) saveterm.leach = terminal; // 2011-03-15 BUG 1908 (don't need to set leach when in a macro)
    }
    else shell.M.detach();

    exit = (M.pipeMode==Midas.PINIT)? 0:EXIT_ALL;
    exit = MA.getOptionMask("/EXIT",exitList,exit);

    MW.addTo(this);

    shell.M.terminal = terminal;
    // revert to previous behavior for 3.8.0, as this message needs to appear in the shellgui (TODO: look into if this message also needs logging NXM-2813)
    if (verbose) terminal.writeln("Welcome to NeXtMidas "+Installation.NM_VERSION+" ...");

    return NORMAL;
  }

  public int process () {
    shell.process();
    if (exit(EXIT_COMMAND)) return FINISH;
    return  NORMAL;
  }

  public int processMessage (Message msg) {
    int status = NORMAL;
    if      (msg.name.equals("EXIT"))                  exit(EXIT_MESSAGE);
    else if (msg.name.equals("MENUEXIT"))              exit(EXIT_MENU);
    else if (msg.name.equals("WINDOW") && msg.info==0) exit(EXIT_WINDOW);
    else if (msg.name.equals("RESIZE"))                MW.resize(0);
    else if (msg.name.equals("CLEAR"))                 clear();
    else status = MW.processMessage(msg);
    return status;
  }

  private boolean exit (int flag) {
    if ((flag&exit)!=0) exiting=true;
    if (exiting && flag!=EXIT_COMMAND) terminal.setTextInput("EXIT");
    return exiting;
  }

  @SuppressWarnings("deprecation")  // for M.terminal - since 3.7.1 for NXM-2813
  public int close () {
    if (attach) {
      M.terminal = saveterm;
      saveterm.leach = null;
    }
    MW.close();
    return NORMAL;
  }

  /** Clear text in terminal window.
      @since NeXtMidas 2.9.0
   */
  public void clear () { mwtext.mtext.removeAll(); }


}
