package nxm.sys.libg;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import nxm.sys.inc.MessageHandler;
import nxm.sys.lib.Command;
import nxm.sys.lib.Message;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Terminal;
import nxm.sys.lib.Time;

/**
  A class to graphically emulate a text based user terminal.

  @author Jeff Schoen
*/
public class GTerminal extends Terminal implements ActionListener, MessageHandler {

  /** Text area for text input and output */
  private MJText   mjtext;
  private MWText   MW;

  /** the text input by the user */
  private String textinput = null;

  /** interrupt flag; has user typed Ctrl-D */
  private int interrupt = 0;
  private int mode;

  /**
     Construct a new GTerminal and open the graphics window.
     @param m the Midas context
     @param mwtext the MWtext graphical text window
   */
  public GTerminal (Midas m, MWText mwtext) {
    M  = m;
    MW = mwtext;
    setupTextArea(mwtext);
  }

  private void setupTextArea (MWText mwtext) {
    mjtext = mwtext.mtext;
    if (mjtext != null) { // Since NeXtMidas 3.5.0. Skip if in Headless state. BUG 2817
      mjtext.addActionListener(this);
    }
  }

  /**
     Sets the input text.
     @param text the input text
   */
  public void setTextInput (String text) {
    textinput = text;
  }

  @Override
  public synchronized void print (String text) {
    // Since 3.1.1: This method was made synchronized so multiple threads don't step over each
    //              other when writing to this terminal
    if (mjtext==null) return;

    mjtext.addText(text);
  }

  private boolean needExit() {
    if (M.pipeMode==Midas.PSTOP) textinput = "EXIT";
    return (M.status==Command.EXIT);
  }

  public String getInput (String prompt, String seed, int flags) {
    mode = flags;
    boolean copy = true;
    if (prompt==null) prompt="";
    if (seed==null) seed="";
    if (mjtext != null) { // Since NeXtMidas 3.5.0. Skip if in Headless state. BUG 2817
      mjtext.setPrompt(prompt);
      mjtext.setInput(seed);
    }
    while (textinput == null && !needExit()) Time.sleep(0.1);
    if (mjtext != null) { // Since NeXtMidas 3.5.0. Skip if in Headless state. BUG 2817
      mjtext.setPrompt("");
      mjtext.setInput("");
      if (mode == -2) mjtext.replace("");
    }
    if ((mode != -2) && (textinput != null)) {
      if (textinput.startsWith("!") && mode != Terminal.INPUT_NO_ESC) copy = false;   // special recall function
      else if (textinput.startsWith("!") && mode == Terminal.INPUT_NO_ESC) textinput=seed;  // BUG 1948
      if (copy) print (prompt+textinput+"\n");  // copy to output window
    }
    String text = textinput;    // copy reference to return variable
    textinput = null;      // re-initialize input string
    mode = 0;
    return text;
  }

  public int getInterrupt() {
    return interrupt;
  }

  public int getRows() {
    return mjtext.getRows()-1;
  }

  public int getColumns() {
    return mjtext.getColumns();
  }

  /** {@inheritDoc}
      @return By default {@link GTerminal} returns <code>false</code>.
      @see Terminal#isExtCmdSupported()
   */
  public boolean isExtCmdSupported() {
    return false;
  }

  public void actionPerformed (ActionEvent e) {
    String action = e.getActionCommand();
    if (action.equals("ENTER")) {
      textinput = mjtext.getInput();
      if (mode == -2) textinput = "\n";
    }
    else if (action.equals("KEYPRESS")) {
      if (mode == -2) {
        textinput = mjtext.getInput();
      }
    }
    else if (action.equals("POPCODE")) {
      if (mode == Terminal.INPUT_NO_ESC) return;  // BUG 1948
      int popcode = e.getModifiers();
      switch (popcode) {
        case -2: textinput = "!LASTREF"; break;
        case -1: textinput = "!LAST"; break;
        case  1: textinput = "!NEXT"; break;
        case  2: textinput = "!NEXTREF"; break;
      }
    }
    else if (action.equals("POP")) {
      if (MW.status!=MWindow.EXIT) MW.pop(-1);
    }
    else if (action.equals("BANNER")) {
      if (MW.status!=MWindow.EXIT) MW.pop(-1);
    }
    else if (action.equals("SELECT")) {
    }
    else if (action.equals("INTERRUPT")) {
      textinput = mjtext.getInput();
      if (mode == -2) textinput = "\n";
      interrupt=1;
    }
    else if (action.equals("BUTTON")) {
      int button = e.getModifiers();
      if (button==2 || button==3) {
        new GMenu (MW,"GTerminal","Copy,Paste,Clear,Configure,Exit",0,0,this);
        mjtext.refreshO();
      }
    }
  }

  public int processMessage (Message msg) {
    if (msg.name.equals("GTERMINAL")) {
      String action = (String)msg.data;
      if (action.equals("CLEAR")) mjtext.removeAll();
      if (action.equals("PASTE")) mjtext.paste();
      if (action.equals("COPY"))  mjtext.copy();
      if (action.equals("CONFIGURE"))
        new GMenu (MW,"GTerminal.cfg",MJText.flagsList,mjtext.getFlags(),GMenu.TOGGLE,this);
      if (action.equals("EXIT")) MW.process("MENUEXIT", 0);  // used by shellgui
    } else if (msg.name.equals("GTERMINAL.CFG")) {
      mjtext.setFlags(msg.info);
    }
    return 0;
  }

  /** Handle the more filter text output.
      @param text The text to display.
   */
  @Override
  public void more (String text) {

    if (morestat<0);
    else if (morestat==0) {
      String ans = getInput("Press RETURN=NextLine, SPACE=NextPage, or Q=Quit: ", "", INPUT_CHAR_CLEAR);
      // Added fix for NXM-2422
      if (ans == null)                  morestat = -1;           // Quit
      else if (ans.startsWith("q"))     morestat = -1;           // Quit
      else if (ans.startsWith("Q"))     morestat = -1;           // Quit
      else if (ans.equals("\n"))        morestat = 1;            // One-Line
      else                              morestat = getRows()-1;  // Full Page
    }
    if (morestat>0) {
      writeln (text);   // not switch over to allow logging at this time, since terminal allows extra settings
      if (mjtext!=null) {
          morestat=morestat-mjtext.getNbrWraps(text);
          morestat = Math.max(0,morestat);
      } else {
        morestat--;
      }
    }
  }
}
