/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/02/07, 18:54
!  AUTHOR(S): KOGA, Junichiro
!  File : PhononPanel.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.plugins.projectmanipulator.phase.resultsviewerpanel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
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.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;

import org.apache.log4j.Logger;

import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.graph.DataPanel;
import ciss.phase_viewer.outputinterface.OutputData;
import ciss.phase_viewer.outputinterface.OutputParser;
import ciss.phase_viewer.outputinterface.OutputParserListener;
import ciss.phase_viewer.plugins.projectmanipulator.phase.resultsviewerpanel.tools.AnimDynmPlPanel;
import ciss.phase_viewer.primitiveguis.ComboButton;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.ChoosableOption;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.ONOFFOption;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.PerlExecPanel;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.PerlScript;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.PerlScriptExecListener;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.PerlScriptOption;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.RangeOption;
import ciss.phase_viewer.primitiveguis.perlscriptexecuters.TextOption;
import ciss.phase_viewer.projectbrowser.ProjectInfo;
import ciss.phase_viewer.projectbrowser.ProjectManipulator;
import ciss.phase_viewer.projectbrowser.tools.LoadingFilePanel;
import ciss.phase_viewer.projectbrowser.tools.NoFilePanel;

/**
 * 振動解析用パネル
 */
public class PhononPanel extends ProjectManipulator {
    private Logger logger = Logger.getLogger(PhononPanel.class.getName());

    private String trj2file = "mode_\\d+.tr2";

    private String gridmol2 = "grid.mol2";

    private String epsfile = "freq\\d*.eps";

    private String phband_file = "phonon_band.eps";

    private String phdos_file = "phonon_dos.eps";

    private String phfree_file = "phonon_free.eps";

    private String phspecific_heat_file = "phonon_specific_heat.eps";

    /** Creates a new instance of PhononPanel */
    public PhononPanel(ProjectInfo projectInfo) {
        super(projectInfo);
    }

    private boolean isGamma = true;

    private void determineType(String fmodeFile) {
        BufferedReader reader = Utils.getReader(fmodeFile);
        isGamma = true;
        try {
            String line = "";
            while ((line = reader.readLine()) != null) {
                if (line.trim().equals("--- Vibrational modes ---")) {
                    line = reader.readLine();
                    String[] ar = line.split("Nqvec");
                    if (ar.length >= 2)
                        isGamma = false;
                    return;
                }
            }
        } catch (IOException ioe) {
        } catch (NullPointerException npe) {
        } finally {
            try {
                reader.close();
            } catch (Exception ex) {
            }
        }
    }

    private JComboBox tr2combo;

    private JComboBox epscombo;

    private String phfree_data_file = "phfree.data";
    private String phheat_data_file = "phheat.data";

    private PHFreePanel phfreePanel;
    private PHHeatPanel phheatPanel;

    class PHHeatPanel extends JPanel implements PerlScriptExecListener {
        PHHeatPanel() {
            if (new File(projectInfo.getProjectDirectory() + phheat_data_file)
                    .exists())
                genGUI();
            else
                add(new NoFilePanel("specific heat file"));
        }

        private Vector data;
        private OutputData outputData;
        private String[] ident;

        private void genGUI() {
            removeAll();
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            JPanel panel = getDataPanel();
            add(panel);
        }

        private JPanel getDataPanel() {
            BufferedReader reader = Utils.getReader(projectInfo
                    .getProjectDirectory() + phheat_data_file);
            String line = "";
            data = new Vector();
            try {
                while ((line = reader.readLine()) != null) {
                    String[] ar = line.trim().split("\\s+");
                    if (line.trim().startsWith("#")) {
                        if (ar.length == 3) {
                            ident = new String[2];
                            for (int i = 0; i < 2; i++)
                                ident[i] = ar[i + 1];
                        }
                    } else {
                        data.add(ar);
                    }
                }
            } catch (IOException ioe) {
            } finally {
                try {
                    reader.close();
                } catch (IOException ioe) {
                }
            }

            String[][] d2d = new String[data.size()][];
            data.copyInto(d2d);
            outputData = new OutputData("specific heat",
                    "specific heat versus temperature", ident, d2d, "");
            DataPanel panel = new DataPanel(outputData);
            logger.info(panel.getPreferredSize());
            panel.setPreferredSize(new Dimension(525, 250));
            return panel;
        }

        public void perlScriptFinished() {
            // TODO Auto-generated method stub
            genGUI();
        }

        public void perlScriptStarted() {
            // TODO Auto-generated method stub
            ;
        }
    }

    class PHFreePanel extends JPanel implements PerlScriptExecListener {
        PHFreePanel() {
            removeAll();
            if (new File(projectInfo.getProjectDirectory() + phfree_data_file)
                    .exists())
                genGUI();
            else
                add(new NoFilePanel("free-energy file"));
        }

        private Vector data;
        private OutputData outputData;
        private String[] ident;

        private void genGUI() {
            removeAll();
            BufferedReader reader = Utils.getReader(projectInfo
                    .getProjectDirectory() + phfree_data_file);
            String line = "";
            data = new Vector();
            try {
                while ((line = reader.readLine()) != null) {
                    String[] ar = line.trim().split("\\s+");
                    if (line.trim().startsWith("#")) {
                        if (ar.length == 5) {
                            ident = new String[4];
                            for (int i = 0; i < 4; i++)
                                ident[i] = ar[i + 1];
                        }
                    } else {
                        data.add(ar);
                    }
                }
            } catch (IOException ioe) {
            } finally {
                try {
                    reader.close();
                } catch (IOException ioe) {
                }
            }

            String[][] d2d = new String[data.size()][];
            data.copyInto(d2d);
            outputData = new OutputData("free energy",
                    "Hermholtz free energy versus temperature", ident, d2d, "");
            DataPanel panel = new DataPanel(outputData);
            panel.setPreferredSize(new Dimension(525, 250));

            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            add(panel);

            revalidate();
        }

        public void perlScriptFinished() {
            // TODO Auto-generated method stub
            genGUI();
        }

        public void perlScriptStarted() {
            // TODO Auto-generated method stub
            ;
        }
    }

    class PHFreeAndHeatPanel extends JPanel {
        PHFreeAndHeatPanel() {
            init();
        }

        private void init() {
            setLayout(new BorderLayout());
            JPanel p = new JPanel();
            p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));

            JPanel pfree = new JPanel();
            pfree.setBorder(new TitledBorder("free energy"));
            JButton btnrunphfree = new JButton("run phfree.pl");
            ComboButton cbfree = new ComboButton(
                    projectInfo.getProjectDirectory(), phfree_file);
            pfree.add(btnrunphfree);
            pfree.add(cbfree);

            JPanel pheat = new JPanel();
            pheat.setBorder(new TitledBorder("specific heat"));
            JButton btnrunphheat = new JButton("run phheat.pl");
            ComboButton cbheat = new ComboButton(
                    projectInfo.getProjectDirectory(), phspecific_heat_file);
            pheat.add(btnrunphheat);
            pheat.add(cbheat);
            p.add(pfree);
            p.add(pheat);

            add(p, BorderLayout.NORTH);

            JTabbedPane pane = new JTabbedPane();

            phfreePanel = new PHFreePanel();
            JPanel phf = new JPanel();
            phf.setLayout(new BorderLayout());
            phf.add(phfreePanel, BorderLayout.NORTH);
            pane.addTab("free energy", phf);

            phheatPanel = new PHHeatPanel();
            JPanel ph = new JPanel();
            ph.setLayout(new BorderLayout());
            ph.add(phheatPanel, BorderLayout.NORTH);
            pane.addTab("specific heat", ph);

            JPanel pp = new JPanel();
            pp.setLayout(new BoxLayout(pp, BoxLayout.Y_AXIS));
            pp.add(pane);
            add(pp, BorderLayout.CENTER);

            btnrunphfree.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    runphfree();
                }
            });

            btnrunphheat.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    runphheat();
                }
            });
        }

    }

    class PHDOSPanel extends JPanel implements OutputParserListener {

        private OutputParser parser;

        PHDOSPanel() {
            init();
        }

        private void init() {
            removeAll();
            String fname = projectInfo.getProjectDirectory()
                    + System.getProperty("file.separator")
                    + projectInfo.getChaseFileManager().getFile("F_PHDOS")
                            .getFileName();
            if (!new File(fname).exists()) {
                add(new NoFilePanel("F_PHDOS"));
                return;
            }
            add(new LoadingFilePanel("F_PHDOS"));
            if (parser == null) {
                parser = projectInfo.getOutputInterface().getParser("F_PHDOS",
                        this);
            }
            parser.setParsed(false);
            parser.doParse();
        }

        public void parseFinished() {
            removeAll();
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            JPanel dataPanel = projectInfo.getOutputInterface().getDataPanel(
                    "F_PHDOS");
            add(dataPanel);
        }

    }

    class PHDOSandPHBandPanel extends JPanel {
        PHDOSandPHBandPanel() {
            setLayout(new BorderLayout());
            JPanel btns = new JPanel();
            btns.setLayout(new BoxLayout(btns, BoxLayout.Y_AXIS));

            JPanel pdos = new JPanel();
            pdos.setBorder(new TitledBorder("phonon DOS"));
            JButton btnrunphdos = new JButton("run phdos.pl");
            ComboButton cbdos = new ComboButton(
                    projectInfo.getProjectDirectory(), phdos_file);
            pdos.add(btnrunphdos);
            pdos.add(cbdos);

            JPanel pband = new JPanel();
            pband.setBorder(new TitledBorder("phonon band"));
            JButton btnrunphband = new JButton("run phband.pl");
            ComboButton cbband = new ComboButton(
                    projectInfo.getProjectDirectory(), phband_file);
            pband.add(btnrunphband);
            pband.add(cbband);

            btns.add(pdos);
            btns.add(pband);

            btnrunphdos.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    runphdos();
                }
            });

            btnrunphband.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    runphband();
                }
            });

            add(btns, BorderLayout.NORTH);

            PHDOSPanel phdospanel = new PHDOSPanel();
            JPanel p = new JPanel();
            p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
            p.add(phdospanel);
            add(p, BorderLayout.CENTER);
        }
    }

    private void createPanelForDispersion() {
        JTabbedPane pane = new JTabbedPane();
        PHDOSandPHBandPanel dosband = new PHDOSandPHBandPanel();
        pane.addTab("dos and band", dosband);

        PHFreeAndHeatPanel freeheat = new PHFreeAndHeatPanel();
        pane.addTab("free energy and specific heat", freeheat);

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(pane);

        revalidate();
    }

    private void runphdos() {
        PerlScript script = new PerlScript("phdos.pl", new File(
                projectInfo.getProjectDirectory()));
        script.setCommand(new String[] { "phdos.data", PerlScriptOption.OPTION });

        PerlScriptOption unit = new ChoosableOption("unit", new String[] {
                "mHa", "meV", "cm-1", "THz" });
        PerlScriptOption erange = new RangeOption("erange");
        PerlScriptOption einc = new TextOption("einc");
        PerlScriptOption dosrange = new RangeOption("dosrange");
        PerlScriptOption dosinc = new TextOption("dosinc");
        PerlScriptOption color = new ONOFFOption("color");
        PerlScriptOption title = new TextOption("title");
        PerlScriptOption width = new TextOption("width");
        PerlScriptOption font = new TextOption("font");

        script.addOptions(unit);
        script.addOptions(erange);
        script.addOptions(einc);
        script.addOptions(dosrange);
        script.addOptions(dosinc);
        script.addOptions(color);
        script.addOptions(title);
        script.addOptions(width);
        script.addOptions(font);

        PerlExecPanel panel = new PerlExecPanel("run phdos.pl", new Dimension(
                400, 250), script);
    }

    private void runphband() {
        PerlScript script = new PerlScript("phband.pl", new File(
                projectInfo.getProjectDirectory()));
        script.setCommand(new String[] { modeData, "phbandcontrol",
                PerlScriptOption.OPTION });

        PerlScriptOption unit = new ChoosableOption("unit", new String[] {
                "mHa", "meV", "cm-1", "THz" });
        PerlScriptOption erange = new RangeOption("erange");
        PerlScriptOption einc = new TextOption("einc");
        PerlScriptOption ptype = new ChoosableOption("ptype", new String[] {
                "lines", "solid_circles" });
        PerlScriptOption color = new ONOFFOption("color");
        PerlScriptOption width = new TextOption("width");

        script.addOptions(unit);
        script.addOptions(erange);
        script.addOptions(einc);
        script.addOptions(ptype);
        script.addOptions(color);
        script.addOptions(width);

        PerlExecPanel pan = new PerlExecPanel("run phband.pl", new Dimension(
                440, 200), script);
    }

    private void runphfree() {
        PerlScript script = new PerlScript("phfree.pl", new File(
                projectInfo.getProjectDirectory()));
        script.setCommand(new String[] { modeData, PerlScriptOption.OPTION });

        PerlScriptOption unit = new ChoosableOption("unit", new String[] {
                "mHa", "meV", "cm-1", "THz" });
        PerlScriptOption erange = new RangeOption("erange");
        PerlScriptOption einc = new TextOption("einc");
        PerlScriptOption trange = new RangeOption("trange");
        PerlScriptOption tinc = new TextOption("tinc");
        PerlScriptOption ntemp = new TextOption("ntemp");
        PerlScriptOption ptype = new ChoosableOption("ptype", new String[] {
                "lines", "solid_circles" });
        PerlScriptOption color = new ONOFFOption("color");
        PerlScriptOption width = new TextOption("width");

        script.addOptions(unit);
        script.addOptions(erange);
        script.addOptions(einc);
        script.addOptions(trange);
        script.addOptions(tinc);
        script.addOptions(ntemp);
        script.addOptions(ptype);
        script.addOptions(color);
        script.addOptions(width);

        PerlExecPanel panel = new PerlExecPanel("run phfree.pl", new Dimension(
                440, 250), script);
        panel.setStdoutFile(new File(projectInfo.getProjectDirectory()
                + phfree_data_file));
        panel.addListener(phfreePanel);

    }

    private void runphheat() {
        PerlScript script = new PerlScript("phheat.pl", new File(
                projectInfo.getProjectDirectory()));
        script.setCommand(new String[] { modeData, PerlScriptOption.OPTION });

        PerlScriptOption cinc = new TextOption("cinc");
        PerlScriptOption trange = new RangeOption("trange");
        PerlScriptOption tinc = new TextOption("tinc");
        PerlScriptOption ntemp = new TextOption("ntemp");
        PerlScriptOption ptype = new ChoosableOption("ptype", new String[] {
                "lines", "solid_circles" });
        PerlScriptOption color = new ONOFFOption("color");
        PerlScriptOption width = new TextOption("width");

        script.addOptions(trange);
        script.addOptions(tinc);
        script.addOptions(ntemp);
        script.addOptions(ptype);
        script.addOptions(color);
        script.addOptions(width);

        PerlExecPanel panel = new PerlExecPanel("run phheat.pl", new Dimension(
                440, 200), script);
        panel.setStdoutFile(new File(projectInfo.getProjectDirectory()
                + phheat_data_file));
        panel.addListener(phheatPanel);
    }

    private void createPanelForGamma() {
        JPanel pmodepl = new JPanel();
        pmodepl.setBorder(new TitledBorder("freq.pl"));
        JButton btnmodepl = new JButton("run freq.pl");
        pmodepl.add(btnmodepl);
        JPanel panimpl = new JPanel();
        panimpl.setBorder(new TitledBorder("animate.pl"));
        JButton btnanimpl = new JButton("run animate.pl");
        panimpl.add(btnanimpl);
        JPanel pbtns = new JPanel();
        pbtns.setLayout(new BoxLayout(pbtns, BoxLayout.X_AXIS));
        pbtns.add(pmodepl);
        pbtns.add(panimpl);
        add(pbtns);

        ComboButton cbanim = new ComboButton(projectInfo.getProjectDirectory(),
                new String[] { trj2file });
        ComboButton cbfreq = new ComboButton(projectInfo.getProjectDirectory(),
                epsfile);
        pmodepl.add(cbfreq);
        panimpl.add(cbanim);

        btnmodepl.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                bootFreqPl();
                // FreqPlPanel panel = new
                // FreqPlPanel(projectInfo.getProjectDirectory(),projectInfo.getChaseFileManager().getFile("F_MODE").getFileName());
            }
        });

        btnanimpl.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                AnimDynmPlPanel panel = new AnimDynmPlPanel(projectInfo
                        .getProjectDirectory(), projectInfo
                        .getChaseFileManager().getFile("F_MODE").getFileName());
            }
        });
    }

    private void bootFreqPl() {
        PerlScript script = new PerlScript("freq.pl", new File(
                projectInfo.getProjectDirectory()));
        PerlScriptOption width = new TextOption("width");
        PerlScriptOption height = new TextOption("height");
        PerlScriptOption nrep = new TextOption("nrep");
        PerlScriptOption solid = new ONOFFOption("solid");
        PerlScriptOption mol = new ONOFFOption("mol");
        PerlScriptOption ig = new TextOption("ignored_modes");

        script.setCommand(new String[] { PerlScriptOption.OPTION, modeData });
        script.addOptions(width);
        script.addOptions(height);
        script.addOptions(nrep);
        script.addOptions(solid);
        script.addOptions(mol);
        script.addOptions(ig);

        PerlExecPanel panel = new PerlExecPanel("run freq.pl", new Dimension(
                400, 200), script);

    }

    private String modeData;

    public void init() {
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        String name = projectInfo.getChaseFileManager().getFile("F_MODE")
                .getFileName();
        modeData = name;
        logger.debug("name: " + name);
        String fname = projectInfo.getProjectDirectory()
                + System.getProperty("file.separator") + name;
        if (!(new File(fname).exists()) || new File(fname).isDirectory()) {
            add(new NoFilePanel("F_MODE"));
            return;
        }

        createPanelForGamma();
        BufferedReader reader = null;
        StringBuffer text = new StringBuffer("");
        try {
            reader = new BufferedReader(new FileReader(fname));
            String str = "";
            while ((str = reader.readLine()) != null) {
                // text += str+System.getProperty("line.separator");
                text.append(str + System.getProperty("line.separator"));
            }
        } catch (Exception exc) {
            logger.error("error in reading " + fname);
            exc.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (Exception exc) {
                exc.printStackTrace();
            }
        }

        JPanel pmode = new JPanel();
        pmode.setLayout(new BoxLayout(pmode, BoxLayout.Y_AXIS));
        JTextPane pane = new JTextPane();
        pane.setPreferredSize(new Dimension(500, 300));
        pane.setEditable(false);
        pane.setBackground(Color.WHITE);
        pane.setText(text.toString());
        pane.setCaretPosition(0);
        JScrollPane scrpane = new JScrollPane(pane);
        pmode.add(scrpane);
        add(pmode);
    }

    public void initializeProject() {
    }

}
