/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/11/30, 14:34
!  AUTHOR(S): KOGA, Junichiro
!  File : TrajectoryPanel.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.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.ACVCaller;
import ciss.phase_viewer.acviewer.ACVData;
import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.atomcoord.Nfdynm2AtomCoords;
import ciss.phase_viewer.atomcoord.io.ExportFileChooser;
import ciss.phase_viewer.atomcoord.io.Exportable;
import ciss.phase_viewer.common.CoordsViewerBooter;
import ciss.phase_viewer.common.StringConstants;
import ciss.phase_viewer.file.ChaseFile;
import ciss.phase_viewer.file.ChaseFileManager;
import ciss.phase_viewer.inputinterface.DataManager;
import ciss.phase_viewer.outputinterface.OutputParser;
import ciss.phase_viewer.outputinterface.OutputParserListener;
import ciss.phase_viewer.plugins.projectmanipulator.phase.PhaseConstants;
import ciss.phase_viewer.plugins.projectmanipulator.phase.resultsviewerpanel.parsers.NfDynmParser;
import ciss.phase_viewer.plugins.projectmanipulator.phase.resultsviewerpanel.tools.AnimDynmPlPanel;
import ciss.phase_viewer.plugins.projectmanipulator.phase.resultsviewerpanel.tools.DynmDiffPanel;
import ciss.phase_viewer.primitiveguis.ComboButton;
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;

/**
 * 
 * @author KOGA, Junichiro
 */
public class TrajectoryPanel extends ProjectManipulator {
    private Logger logger = Logger.getLogger(TrajectoryPanel.class.getName());

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

    public void init() {
        removeAll();
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(new TrajectoryPanelPanel(projectInfo));
    }

    public void initializeProject() {
    }

}

class TrajectoryPanelPanel extends JPanel implements ACVCaller,
        OutputParserListener, Exportable {
    private Logger logger = Logger.getLogger(TrajectoryPanelPanel.class
            .getName());
    private ChaseFileManager cfManager;

    private ProjectInfo projectInfo;

    private String projDir;

    private String nfdynmdata;

    private File nfdynmFile;

    private boolean fileExists;

    private Nfdynm2AtomCoords dynmParser;
    private Nfdynm2AtomCoords[] dynmParsers;

    protected TrajectoryPanelPanel(ProjectInfo projectInfo) {
        super();
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.projectInfo = projectInfo;
        this.cfManager = projectInfo.getChaseFileManager();
        this.projDir = projectInfo.getProjectDirectory();
        this.nfdynmdata = cfManager.getFile("F_DYNM").getFileName();
        nfdynmFile = new File(projDir + System.getProperty("file.separator")
                + nfdynmdata);
        fileExists = nfdynmFile.exists();
        init();
    }

    private OutputParser parser;
    private ChaseFile cf;
    private boolean reac = false;
    private String[] reacfiles;

    private void init() {
        if (!fileExists) {
            add(new NoFilePanel("F_DYNM"));
            return;
        }
        cf = projectInfo.getChaseFileManager().getFile("F_DYNM");
        if (nfdynmFile.length() == 0) {
            add(new NoFilePanel("F_DYNM", "is invalid"));
            // return;
        }

        dynmParser = new Nfdynm2AtomCoords(projDir
                + System.getProperty("file.separator") + nfdynmdata);
        add(new LoadingFilePanel("F_DYNM"));
        if (parser == null) {
            parser = projectInfo.getOutputInterface().getParser("F_DYNM", this);
        }
        reacfiles = new File(projectInfo.getProjectDirectory())
                .list(new FilenameFilter() {
                    public boolean accept(File arg0, String arg1) {
                        if (arg1.matches(cf.getFileName() + ".reac\\d+"))
                            return true;
                        if (arg1.matches(cf.getFileName() + ".converged"))
                            return true;
                        return false;
                    }
                });
        if (reacfiles != null && reacfiles.length != 0) {
            reac = true;
            logger.info("found multiple F_DYNM files.");
            parser.resetFiles();
            dynmParsers = new Nfdynm2AtomCoords[reacfiles.length];
            for (int i = 0; i < reacfiles.length; i++) {
                logger.debug("F_ENF file: " + reacfiles[i]);
                String dynmdata = projectInfo.getProjectDirectory()
                        + System.getProperty("file.separator") + reacfiles[i];
                parser.addFile(dynmdata);
                dynmParsers[i] = new Nfdynm2AtomCoords(dynmdata);
            }
        }
        parser.setParsed(false);
        parser.doParse();
    }

    private JComboBox comboFrame;
    private JLabel numframes;
    private JLabel path;
    private JComboBox combopath;
    private JTextField tfstart;
    private JTextField tfend;
    private JTextField tfgap;
    private JPanel pframe;
    private JPanel firstRow() {
        Nfdynm2AtomCoords dynm = dynmParser;
        if (reac)
            dynm = dynmParsers[0];
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

        JPanel ppath = new JPanel();
        ppath.setBorder(new TitledBorder("file name"));
        if (!reac) {
            path = new JLabel(nfdynmFile.getName());
            ppath.add(path);
        } else {
            combopath = new JComboBox(reacfiles);
            JPanel pc = new JPanel();
            pc.add(combopath);
            ppath.add(pc);
        }

        // numframes = new JLabel(String.valueOf(dynm.getNumFrames()));
        // JPanel pnumframes = new JPanel();
        // pnumframes.setBorder(new TitledBorder("nframes"));
        // pnumframes.add(numframes);

        String[] choices = new String[dynm.getNumFrames() + 1];
        choices[0] = "all";
        for (int i = 0; i < dynm.getNumFrames(); i++) {
            choices[i + 1] = String.valueOf(i);
        }
        comboFrame = new JComboBox(choices);
        comboFrame.setEditable(true);
        // comboFrame.setPreferredSize(new Dimension(40, 20));
        pframe = new JPanel();
        pframe.setBorder(new TitledBorder("select frame (num. frames: "
                + String.valueOf(dynm.getNumFrames()) + ")"));
        pframe.add(comboFrame);

        tfstart = new JTextField(4);
        tfstart.setText("0");
        JPanel pstart = new JPanel();
        pstart.setBorder(new TitledBorder("start"));
        pstart.add(tfstart);

        tfend = new JTextField(4);
        tfend.setText(String.valueOf(dynm.getNumFrames() - 1));
        JPanel pend = new JPanel();
        pend.setBorder(new TitledBorder("end"));
        pend.add(tfend);

        tfgap = new JTextField(4);
        tfgap.setText("1");
        JPanel pgap = new JPanel();
        pgap.setBorder(new TitledBorder("gap"));
        pgap.add(tfgap);

        JPanel btnpanel = new JPanel();
        btnpanel.setLayout(new BoxLayout(btnpanel, BoxLayout.X_AXIS));
        JButton bootEditor = new JButton("boot editor");
        JButton bootViewer = new JButton("viewer");
        JButton btnexport = new JButton("export");
        // btnpanel.add(bootEditor);
        btnpanel.add(bootViewer);
        btnpanel.add(btnexport);

        JButton diff = new JButton("diff");
        diff.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String fil = nfdynmFile.getAbsolutePath();
                if (reac) {
                    fil = projectInfo.getProjectDirectory()
                            + System.getProperty("file.separator")
                            + reacfiles[combopath.getSelectedIndex()];
                }
                DynmDiffPanel diff = new DynmDiffPanel(fil, fil);
            }
        });

        if (reac) {
            combopath.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    int index = combopath.getSelectedIndex();
                    Nfdynm2AtomCoords dynm = dynmParsers[index];
                    tfend.setText(String.valueOf(dynm.getNumFrames()));
                    //numframes.setText(String.valueOf(dynmParsers[index]
                    //        .getNumFrames()));
                    ((DefaultComboBoxModel) comboFrame.getModel())
                            .removeAllElements();
                    ((DefaultComboBoxModel) comboFrame.getModel())
                            .addElement("all");
                    for (int i = 0; i < dynmParsers[index].getNumFrames(); i++) {
                        ((DefaultComboBoxModel) comboFrame.getModel())
                                .addElement(String.valueOf(i));
                    }
                    pframe.setBorder(new TitledBorder("select frame (num. frames: "
                            + String.valueOf(dynm.getNumFrames()) + ")"));
                    revalidate();
                }
            });
            combopath.setSelectedIndex(0);
        }
        btnpanel.add(diff);
        //
        // bootEditor.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // ProjectBrowserUtils.bootTextViewer(nfdynmFile.getAbsolutePath());
        // }
        // });

        bootViewer.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    bootViewerBooter();
                } catch (Exception ee) {
                    ee.printStackTrace();
                }
            }
        });

        btnexport.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                bootExporter();
            }
        });

        // p.add(ppath);
        // p.add(pnumframes);
        JPanel paa = new JPanel();
        paa.setLayout(new GridLayout(1, 3));
        paa.add(ppath);
        paa.add(pframe);
        JPanel pse = new JPanel();
        pse.setLayout(new BoxLayout(pse, BoxLayout.X_AXIS));
        pse.add(pstart);
        pse.add(pend);
        pse.add(pgap);
        paa.add(pse);
        JPanel ppp = new JPanel();
        ppp.setLayout(new BoxLayout(ppp, BoxLayout.Y_AXIS));
        ppp.add(paa);
        ppp.add(btnpanel);
        p.add(ppp);

        return p;
    }

    private void bootExporter() {
        // ExporterGUI exp = new ExporterGUI(this);
        ExportFileChooser efc = new ExportFileChooser(this, this);
    }

    private void bootViewerBooter() {
        Vector frames = null;
        Nfdynm2AtomCoords dynm = dynmParser;
        String fname = nfdynmdata;
        if (reac) {
            dynm = dynmParsers[combopath.getSelectedIndex()];
            fname = reacfiles[combopath.getSelectedIndex()];
        }
        String choi = (String) comboFrame.getSelectedItem();
        if (choi == null || choi.length() == 0) {
            logger.error("invalid choice.");
            return;
        }
        if (choi.equals("all")) {
            try {
                int istart = Integer.parseInt(tfstart.getText().trim());
                int iend = Integer.parseInt(tfend.getText().trim());
                int igap = Integer.parseInt(tfgap.getText().trim());
                if (istart < 0 || igap > iend) {
                    logger.error("invalid specifcation for the start, end or gap parameter");
                    logger.error("using the default values");
                } else {
                    dynm.setStartEndGap(istart, iend, igap);
                }
            } catch (NumberFormatException nfe) {
                logger.error("invalid specifcation for the start, end or gap parameter");
                logger.error("using the default values");
            }
            frames = dynm.getFrames();
        } else {
            int framenum = 0;
            try {
                framenum = Integer.parseInt(choi);
            } catch (NumberFormatException npe) {
                logger.error("enter an integer value for 'select frame'");
                return;
            }
            AtomCoords ac = dynm.getFrameAt(framenum);
            frames = new Vector();
            frames.add(ac);
        }
        DataManager manager = new DataManager("foo", PhaseConstants.TABLESPEC,
                false);
        manager.parse();
        ACVData acvdata = new ACVData(this, frames, projDir,
                manager.getInputInterface(), StringConstants.phase_atom_tag);
        acvdata.setFileName(fname);
        CoordsViewerBooter cvb = new CoordsViewerBooter(acvdata, 0);
        cvb.boot();
    }

    private JPanel secondRow() {
        JPanel ret = new JPanel();
        ret.setBorder(new TitledBorder("dynm2tr2"));
        ret.setLayout(new BoxLayout(ret, BoxLayout.X_AXIS));
        JButton btn = new JButton("run dynm2tr2");
        ComboButton cb = new ComboButton(projectInfo.getProjectDirectory(),
                "dynm.tr2");
        ret.add(btn);
        ret.add(cb);
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                AnimDynmPlPanel panel = new AnimDynmPlPanel(projectInfo
                        .getProjectDirectory(), nfdynmdata, "dynm2tr2.pl",
                        new String[] { "dynm.tr2", "grid.mol2" });
            }
        });

        return ret;
    }

    public boolean save(AtomCoords[] coords) {
        return false;
    }

    public void save(AtomCoords coords) {
    }

    public void parseFinished() {
        removeAll();
        add(firstRow());
        // add(secondRow());
        add(projectInfo.getOutputInterface().getDataPanel("F_DYNM"));
        revalidate();
    }

    public AtomCoords[] getCoordsToExport() {
        Vector vec = null;
        if (!reac)
            vec = dynmParser.getFrames();
        else
            vec = dynmParsers[combopath.getSelectedIndex()].getFrames();
        AtomCoords[] cds = new AtomCoords[vec.size()];
        vec.copyInto(cds);
        return cds;
    }

    public void coordsExported(AtomCoords[] coords, String type, String fileName) {
    }

}
