package nxm.ucl.prim;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import nxm.sys.lib.Message;
import nxm.sys.lib.Midas;
import nxm.sys.libg.GPrimitive;
import nxm.sys.libg.MBox;
import nxm.sys.libg.MJFrame;
import nxm.sys.libg.MWindow;
import nxm.sys.libg.MidasBean;
import nxm.sys.libg.MidasDisplay;
import nxm.sys.prim.plot;

/**
 * This demonstrates one way of embedding JavaBeans into a primitive. <br>
 * <br>
 * Here {@link MidasBean#createBean(Midas,String,MidasDisplay,String)} is used to create a few JavaBeans of existing
 * NeXtMidas macros and primitives so they can be inserted into a Swing component. This requires user interaction to
 * fully test. Need to check if middle mouse works correctly on plots and if drag box shows on plots.
 * @see MidasBean
 * @since NeXtMidas 3.8.1
 */
public class midasbeantest extends GPrimitive {
  private boolean isDone = false;

  /** Create the frame (window) to use. */
  final MJFrame frame = new MJFrame("beandemo", new MBox(MWindow.DEFAULT_WINDOW_POSITION));

  /** Create the content pane for the frame. */
  final JPanel panel = new JPanel();

  /** list of created MidasBean for cleanup in close() */
  private ArrayList<MidasBean> midasBeans = new ArrayList<>();

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

  public int open () {
    final String text = "\nYou should see 10 panels including this one:\n" +
        "   First: a line plot with a \n" +
        "              Y min/max of 0 to 1,\n" +
        "   Second: a List2, and \n" +
        "   Next 8: sd360s \n\n" +
        "You should not see any errors:\n\n"
        + "In the sd360 panels:\n\n"
        + "1 - test middle mouse button menu\n"
        + "2 - test right click and left click drag box\n"
        + "    there should be no lag on the graphics\n"
        + "3 - Bring up the Export/Scale/Query Menus from \n"
        + "    the mmb menu, these should stay in front.\n"
        + "When finished, exit by clicking the 'X'";
    /* Setup the panel/frame. */
    panel.setLayout(new GridLayout(2, 5));
    frame.setContentPane(panel);
    frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    // define MW to avoid NPE from mouse overs
    MW = new MWindow("BEANDEMO", this);
    frame.setMWindow(this.MW);
    frame.setVisible(true);
    /* Automatically close the window when the user presses the 'X'. */
    frame.addWindowListener(new WindowCloser());

    /* Add a Swing component. */
    JTextArea textArea = new JTextArea(text);
    // so the text is not off the screen
    textArea.setLineWrap(true);
    // so the text wraps by word and not character
    textArea.setWrapStyleWord(true);
    // make the text area scrollable by putting it into a scroll pane.
    JScrollPane textPane = new JScrollPane(textArea);
    panel.add(textPane);

    textArea.setBackground(Color.black);
    textArea.setForeground(Color.white);

    /* Create a few Midas Displays and add them to the panel. */
    MidasDisplay world = new MidasDisplay();
    panel.add(world);
    MidasDisplay list = new MidasDisplay();
    panel.add(list);
    MidasBean bean = MidasBean.createBean(M, "plot world ", world, "worldID");

    midasBeans.add(bean);
    alterWorldPlot(bean, (plot) bean.getCommand());

    midasBeans.add(MidasBean.createBean(M, "list2 fftdemo", list, "listID"));
    // Create many sd360s to test display with high processing.
    for (int i = 1; i <= 7; i++) {
      MidasDisplay md = new MidasDisplay();
      panel.add(md);
      midasBeans.add(MidasBean.createBean(M, "sd360/beanid=beandemo_bean 3e10",
          (MidasDisplay) panel.getComponent(2 + i), "sd360ID" + i));

    }

    return NORMAL;
  }

  private void alterWorldPlot (MidasBean bean, final plot plotPrim) {
    plotPrim.setType("LINE");
    plotPrim.closeFile("*");
    plotPrim.openFile("fftdemo");

    plotPrim.MP.setAxis("FRAME");
    plotPrim.MP.setScale("FIX");
    plotPrim.MP.setXBounds(2e6, 3e6);
    plotPrim.MP.setYBounds(0, 1);
    plotPrim.MP.setReadout("+ONAXIS");
    plotPrim.MP.setAxis("+LNUMBERS|+TNUMBERS|-GRID");
  }

  public int process () {
    if (isDone) {
      return FINISH;
    }
    else {
      return NOOP;
    }
  }

  public int close () {
    for (MidasBean bean : midasBeans) {
      // if (verbose) M.type("DEBUG: Closing "+bean);
      bean.close();
    }
    return NORMAL;
  }

  public int processMessage (Message msg) {
    System.out.println("Got msg " + msg);

    if (msg.getName().equalsIgnoreCase("EXIT")) {
      graphicsDone();
    }

    return NORMAL;
  }

  /** Cleans up and closes the window when done. */
  private void graphicsDone () {
    if (frame != null) {
      frame.setVisible(false);
      frame.dispose();
    }
    isDone = true;
  }

  /** This will end the primitive when the user exits the window. */
  private class WindowCloser extends WindowAdapter {
    public void windowClosing (WindowEvent e) {
      graphicsDone();
    }
  }
}
