/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2007/03/27 19:29:09
!  AUTHOR(S): KOGA, Junichiro
!  File : PerlExecPanel.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.primitiveguis.perlscriptexecuters;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

import org.apache.log4j.Logger;

import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.mainpanel.InternalFrameChase;

/**
 * PHASEなどに付属するのPerlスクリプトを実行するGUI
 * 
 * @author jkoga
 * 
 */
public class PerlExecPanel extends InternalFrameChase {
    private Logger logger = Logger.getLogger(PerlExecPanel.class.getName());

    private PerlScript perlScript;

    private PerlScriptOption[] options;

    private int numCols = 4;

    private int numRows;

    private File stdoutFile;
    private File erroutFile;

    private Vector listeners;

    public PerlExecPanel(String title, Dimension dim, PerlScript perlScript) {
        super(title, true, true, true, true, dim);
        this.perlScript = perlScript;
        this.options = perlScript.getOptions();
        init();
    }

    public void addListener(PerlScriptExecListener listener) {
        if (listeners == null)
            listeners = new Vector();
        listeners.add(listener);
    }

    public void removeListener(PerlScriptExecListener listener) {
        if (listeners == null)
            return;
        listeners.remove(listener);
    }

    public PerlExecPanel(String title, Dimension dim,
            PerlScriptOption[] options, int numCols) {
        super(title, true, true, true, true, dim);
        this.options = options;
        this.numCols = numCols;
        init();
    }

    private boolean closeAfterOK = true;

    public void closeAfterOK(boolean closeAfterOK) {
        this.closeAfterOK = closeAfterOK;
    }

    /**
     * 標準出力をリダイレクトするファイルを指定. デフォルトではlogger.info(...)
     * 
     * @param stdoutFile
     *            上記のファイル
     */
    public void setStdoutFile(File stdoutFile) {
        this.stdoutFile = stdoutFile;
    }

    /**
     * 標準エラー出力をリダイレクトするファイルを指定. デフォルトではlogger.error(...)
     * 
     * @param erroutFile
     */
    public void setErroutFile(File erroutFile) {
        this.erroutFile = erroutFile;
    }

    private void init() {
        Container container = getContentPane();
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
        JPanel popts = new JPanel();
        if (options != null) {
            numRows = (int) Math.ceil((double) options.length
                    / (double) numCols);
            popts.setLayout(new GridLayout(numRows, numCols));
            for (int i = 0; i < options.length; i++) {
                JComponent[] component = options[i].getAssociatedGUI();
                for (int j = 0; j < component.length; j++)
                    popts.add(component[j]);
            }
        }

        JPanel btnpanel = new JPanel();
        btnpanel.setLayout(new BoxLayout(btnpanel, BoxLayout.X_AXIS));
        JButton okbutton = new JButton("OK");
        JButton cancelbutton = new JButton("cancel");
        btnpanel.add(okbutton);
        btnpanel.add(cancelbutton);

        container.add(popts);
        container.add(btnpanel);

        cancelbutton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                dispose();
            }
        });

        okbutton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                doOKAction();
                if (closeAfterOK)
                    dispose();
            }

        });

    }

    public void disose() {
        listeners = null;
        super.dispose();
    }

    private void doOKAction() {

        if (listeners != null)
            for (int i = 0; i < listeners.size(); i++)
                ((PerlScriptExecListener) listeners.get(i)).perlScriptStarted();

        BufferedReader[] reader = perlScript.exec();
        new Thread(new Stdout(reader[0])).start();
        new Thread(new Stderrout(reader[1])).start();
    }

    class Stdout implements Runnable {
        private BufferedReader reader;

        Stdout(BufferedReader reader) {
            this.reader = reader;
        }

        public void run() {
            String line = "";
            PrintWriter writer = null;
            if (stdoutFile != null)
                writer = Utils.getPrintWriter(stdoutFile.getAbsolutePath());

            try {
                while ((line = reader.readLine()) != null) {
                    if (writer == null)
                        logger.info(line);
                    else
                        writer.println(line);
                }
            } catch (IOException ioe) {
            } finally {
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
                try {
                    reader.close();
                } catch (IOException ioe) {
                }
            }
            if (listeners != null)
                for (int i = 0; i < listeners.size(); i++)
                    ((PerlScriptExecListener) listeners.get(i))
                            .perlScriptFinished();
        }
    }

    class Stderrout implements Runnable {
        private BufferedReader reader;

        Stderrout(BufferedReader reader) {
            this.reader = reader;
        }

        public void run() {
            String line = "";
            PrintWriter writer = null;
            if (erroutFile != null)
                writer = Utils.getPrintWriter(erroutFile.getAbsolutePath());

            try {
                while ((line = reader.readLine()) != null)
                    if (writer == null)
                        logger.error(line);
                    else
                        writer.println(line);
            } catch (IOException ioe) {
            } finally {
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
                try {
                    reader.close();
                } catch (IOException ioe) {
                }
            }
        }
    }

}
