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.JPanel;
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.

    @see MidasBean

    @author  J. Czechowski IV
*/
public class beandemo extends GPrimitive {
  private boolean isDone = false;

  /** Create the frame (window) to use. */
  //final JFrame frame = new JFrame("beandemo");  // changed to MJFrame for setup of Graphics better
  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 beandemo () {}

  public int open () {
    final String text = "\nYou should see:\n"+
                         "   Top-Right: a line plot with a \n" +
                         "              Y min/max of 0 to 1,\n" +
                         "   Bottom-Left: a List2, and \n" +
                         "   Bottom-Right: a sd360 \n\n" +
                         "You should not see any errors:\n\n";

    /* Setup the panel/frame. */
    panel.setLayout(new GridLayout(2,2));
    frame.setContentPane(panel);
    frame.setSize(600,600);
    // define MW to avoid NPE from mouse overs
    MW = new MWindow("BEANDEMO", this);
    frame.setMWindow(this.MW);

    /* Automatically close the window when the user presses the 'X'. */
    frame.addWindowListener(new WindowCloser());

    /* Add a Swing component. */
    JTextArea textArea = new JTextArea(text);     panel.add(textArea);

    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);
    MidasDisplay sd360 = new MidasDisplay();      panel.add(sd360);

    /* The frame and the MidasDisplay panels must be visible before creating
       the MidasBean's. If you do not do this you will experience refresh
       problems in PLOT.
     */
    frame.setVisible(true);

    /* Create the beans that will occupy the given Midas Displays. */
    MidasBean bean = MidasBean.createBean(M, "plot world ",   world, "worldID");
    midasBeans.add(bean);
    midasBeans.add(MidasBean.createBean(M, "list2 fftdemo", list, "listID"));
    midasBeans.add(MidasBean.createBean(M, "sd360/beanid=beandemo_bean 3e10", sd360, "sd360ID"));

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

    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();
    }
  }
}
