/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/06/22, 18:25
!  AUTHOR(S): KOGA, Junichiro
!  File : MonitorPanel.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.jobcontrol;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Set;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToggleButton;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;

import ciss.phase_viewer.common.Resources;
import ciss.phase_viewer.file.ChaseFile;
import ciss.phase_viewer.file.Monitorable;
import ciss.phase_viewer.main.PluginLoader;
import ciss.phase_viewer.projectbrowser.ProjectInfo;
import ciss.phase_viewer.ssh.SessionCreator;
import ciss.phase_viewer.ssh.hosts.HostInfo;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * ジョブ監視のためのパネル
 * 
 * @author
 */
public class MonitorPanelPanel extends JPanel implements ChartProgressListener,
        MonitorPanelInterface {
    private boolean drawingChart = false;

    private HostInfo targetHost;

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.jfree.chart.event.ChartProgressListener#chartProgress(org.jfree.chart
     * .event.ChartProgressEvent)
     */
    public void chartProgress(ChartProgressEvent arg0) {
        if (arg0.getType() == ChartProgressEvent.DRAWING_STARTED)
            drawingChart = true;
        else if (arg0.getType() == ChartProgressEvent.DRAWING_FINISHED)
            drawingChart = false;
    }

    private org.apache.log4j.Logger logger = org.apache.log4j.Logger
            .getLogger(MonitorPanelPanel.class.getName());

    private ProjectInfo projectInfo;

    private ChaseFile[] chaseFile;

    private Session session;

    /**
     * 
     * @param projectInfo
     *            モニターしたいプロジェクトの情報
     * @param targetHost
     *            対象ホスト; nullの場合localhost.
     */
    public MonitorPanelPanel(ProjectInfo projectInfo, HostInfo targetHost) {
        this.projectInfo = projectInfo;
        this.targetHost = targetHost;
        init();
    }

    public void reset() {
        try {
            monitorTextArea.setText("");
            monitorButton.setSelected(false);
            graphButton.setSelected(false);
            monitorable.destroyGraph();
            monitorable.stopMonitor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run() {
        // try {
        // Thread.sleep(1500);
        monitorButton.setSelected(true);
        monitorButtonToggled();
        // } catch (InterruptedException e) {
        // }
    }

    public void monitorButtonToggled() {
        if (targetHost.isLocalHost())
            session = null;
        else {
            if (session != null)
                session.disconnect();
            try {
                session = SessionCreator.getSession(targetHost);
                try {
                    session.sendKeepAliveMsg();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } catch (JSchException e) {
                e.printStackTrace();
            }
        }

        if (monitorable != null && monitorButton.isSelected()) {
            if (monitorable != null)
                monitorable.stopMonitor();
            monitorable.monitor(session, monitorTextArea);
            graphButton.setEnabled(monitorable
                    .isGraphCreatable(monitorTextArea));
        } else if (monitorable != null && !monitorButton.isSelected()) {
            monitorable.stopMonitor();
            graphButton.setEnabled(false);
            graphButton.setSelected(false);
            monitorable.destroyGraph();
            // try {
            // setSelected(true);
            // } catch (PropertyVetoException pve) {
            // }
        }
    }

    public void setTargetHost(HostInfo targetHost) {
        if (!this.targetHost.getName().equals(targetHost.getName())) {
            monitorTextArea.setText("");
            monitorButton.setSelected(false);
            graphButton.setSelected(false);
        }
        this.targetHost = targetHost;
    }

    private void init() {
        ChaseFile[] cfs = projectInfo.getChaseFileManager().getFiles();
        if (cfs == null || cfs.length == 0) {
            logger.error("invalid files!");
            return;
        }

        Vector validFiles = new Vector();
        for (int i = 0; i < cfs.length; i++) {
            logger.debug("cfs: " + cfs[i]);
            if (cfs[i].isMonitorable()) {
                validFiles.addElement(cfs[i]);
            }
        }

        if (validFiles.size() == 0) {
            logger.error("no monitorable files.");
            return;
        }

        chaseFile = new ChaseFile[validFiles.size()];
        validFiles.copyInto(chaseFile);

        JPanel fileMonitor = getFileMonitorPanel();

        JButton btnclose = new JButton("close");
        // Container container = getContentPane();
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(fileMonitor);
        // container.add(btnclose);
        // btnclose.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent ae) {
        // dispose();
        // }
        // });

        // addInternalFrameListener(new InternalFrameListener() {
        //
        // public void internalFrameActivated(InternalFrameEvent e) {
        // }
        //
        // public void internalFrameClosed(InternalFrameEvent e) {
        // if (session != null)
        // session.disconnect();
        // }
        //
        // public void internalFrameClosing(InternalFrameEvent e) {
        // }
        //
        // public void internalFrameDeactivated(InternalFrameEvent e) {
        // }
        //
        // public void internalFrameDeiconified(InternalFrameEvent e) {
        // }
        //
        // public void internalFrameIconified(InternalFrameEvent e) {
        // }
        //
        // public void internalFrameOpened(InternalFrameEvent e) {
        // }
        //
        // });
    }

    private JComboBox fileSelector;

    private JTextArea monitorTextArea;

    private Monitorable monitorable;

    private JToggleButton monitorButton;

    private JToggleButton graphButton;

    /**
     * グラフ描画ボタンのsetSelectedメソッドを呼ぶ.
     * 
     * @param sel
     *            選択したい場合true.
     */
    public void setGraphButtonSelected(boolean sel) {
        if (graphButton != null) {
            logger.debug("calling graphButton.setSelected(" + sel + ")");
            ActionListener[] al = graphButton.getActionListeners();
            if (al != null)
                for (int i = 0; i < al.length; i++)
                    graphButton.removeActionListener(al[i]);

            graphButton.setSelected(sel);

            if (al != null)
                for (int i = 0; i < al.length; i++)
                    graphButton.addActionListener(al[i]);
        }
    }

    private JPanel getFileMonitorPanel() {
        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        JPanel pbtns = new JPanel();
        pbtns.setLayout(new BoxLayout(pbtns, BoxLayout.X_AXIS));

        String[] idents = new String[chaseFile.length];
        for (int i = 0; i < idents.length; i++) {
            idents[i] = chaseFile[i].getIdentifier().getValue();
        }
        fileSelector = new JComboBox(idents);
        monitorButton = new JToggleButton(
                Resources.getIcon(Resources.VCRPlay20));
        monitorButton.setToolTipText("toggle monitor");

        graphButton = new JToggleButton(
                Resources.getIcon(Resources.LINEGRAPH20));
        graphButton.setEnabled(false);

        JPanel psele = new JPanel();
        psele.setBorder(new TitledBorder("select file to monitor"));
        psele.setLayout(new BoxLayout(psele, BoxLayout.X_AXIS));
        psele.add(fileSelector);
        pbtns.add(psele);
        pbtns.add(monitorButton);
        pbtns.add(graphButton);
        p.add(pbtns, BorderLayout.NORTH);

        monitorTextArea = new JTextArea();
        monitorTextArea.setEditable(false);
        JScrollPane scrpane = new JScrollPane(monitorTextArea);
        p.add(scrpane, BorderLayout.CENTER);

        fileSelector.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                fileSelected();
            }
        });

        monitorButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                monitorButtonToggled();
                // if (targetHost.isLocalHost())
                // session = null;
                // if (session == null && !targetHost.isLocalHost()) {
                // try {
                // session = SessionCreator.getSession(targetHost);
                // } catch (JSchException e) {
                // e.printStackTrace();
                // }
                // }
                // if (session != null && !session.isConnected()) {
                // try {
                // session = SessionCreator.getSession(targetHost);
                // } catch (JSchException e) {
                // e.printStackTrace();
                // }
                // }
                // if (monitorable != null && monitorButton.isSelected()) {
                // monitorable.monitor(session, monitorTextArea);
                // graphButton.setEnabled(monitorable
                // .isGraphCreatable(monitorTextArea));
                // } else if (monitorable != null &&
                // !monitorButton.isSelected()) {
                // monitorable.stopMonitor();
                // graphButton.setEnabled(false);
                // graphButton.setSelected(false);
                // monitorable.destroyGraph();
                // // try {
                // // setSelected(true);
                // // } catch (PropertyVetoException pve) {
                // // }
                // }
            }
        });

        graphButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (monitorable != null) {
                    if (graphButton.isSelected()) {
                        monitorable.createGraphFrom(monitorTextArea);
                    } else {
                        logger.debug("destroying graph");
                        monitorable.destroyGraph();
                        // try {
                        // setSelected(true);
                        // } catch (PropertyVetoException pve) {
                        // }
                    }
                }
            }
        });

        monitorTextArea.addCaretListener(new CaretListener() {
            public void caretUpdate(CaretEvent ce) {
                if (monitorable != null)
                    graphButton.setEnabled(monitorable
                            .isGraphCreatable(monitorTextArea));
                else
                    graphButton.setEnabled(false);
            }
        });

        fileSelector.setSelectedIndex(0);

        return p;
    }

    private HashMap monitorCache = new HashMap();

    private void fileSelected() {
        monitorButton.setSelected(false);
        setGraphButtonSelected(false);
        graphButton.setEnabled(false);
        if (monitorable != null) {
            monitorable.stopMonitor();
            monitorable.destroyGraph();
        }

        monitorTextArea.setText("");
        ChaseFile selectedFile = chaseFile[fileSelector.getSelectedIndex()];
        Object obj = monitorCache.get(selectedFile.getIdentifier().getValue());
        if (obj == null) {
            String path = selectedFile.getMonitorPath();
            monitorable = (Monitorable) PluginLoader.instantiate(path,
                    new Object[] { projectInfo });
            monitorable.setMonitorPanel(this);
            monitorCache.put(selectedFile.getIdentifier().getValue(),
                    monitorable);
        } else {
            monitorable = (Monitorable) obj;
        }
        //
        // try {
        // setSelected(true);
        // } catch (PropertyVetoException pve) {
        // }
    }

    private void stopAll() {
        Set keySet = monitorCache.keySet();
        if (keySet == null) {
            return;
        }
        Object[] foo = keySet.toArray();
        if (foo == null || foo.length == 0) {
            return;
        }
        for (int i = 0; i < foo.length; i++) {
            Monitorable mon = (Monitorable) monitorCache.get(foo[i]);
            if (mon != null) {
                mon.stopMonitor();
            }
        }
    }

    protected void finalize() throws Throwable {
        stopAll();
        if (session != null) {
            session.disconnect();
        }
    }

}
