/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2006/07/25, 11:12
!  AUTHOR(S): KOGA, Junichiro
!  File : SymmKpointPanel.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.fbz.edit;

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.J3DPanel;
import ciss.phase_viewer.acviewer.fbz.FBZ;
import ciss.phase_viewer.acviewer.fbz.Kpoint;
import ciss.phase_viewer.acviewer.fbz.KpointGenerator;
import ciss.phase_viewer.acviewer.fbz.KpointsListener;
import ciss.phase_viewer.acviewer.fbz.WignerSeitzCell;
import ciss.phase_viewer.common.Utils;

/**
 * 対称点を表示したりうんたらかんたらしたり.
 * 
 * @author
 */
public class SymmKpointPanel extends JPanel implements KpointGenerator,
        KpointsListener {
    private Logger logger = Logger.getLogger(SymmKpointPanel.class.getName());

    private FBZ fbz;

    private WignerSeitzCell wscell;

    private String bandkptin;

    private JTextField textdk;

    private JTable jTable;

    private KpointTableModel tableModel;

    private String[] columnNames = { "nx", "ny", "nz", "symbol" };

    private KpointGenerator kpointGenerator = null;

    /** Creates a new instance of SymmKpointPanel */
    public SymmKpointPanel(J3DPanel basePanel) {
        fbz = (FBZ) basePanel;
        wscell = fbz.getFBZ();
        init();
    }

    private void init() {
        String dir = fbz.getParentDirectory();
        bandkptin = dir + System.getProperty("file.separator") + "bandkpt.in";
        textdk = new JTextField("0.02");
        JPanel ptext = new JPanel();
        ptext.setLayout(new BoxLayout(ptext, BoxLayout.X_AXIS));
        ptext.setBorder(new TitledBorder("enter dk"));
        ptext.add(textdk);

        wscell = fbz.getFBZ();
        wscell.addKPointListener(this);
        Kpoint[] initKpts = wscell.getSelectedKpoints();
        tableModel = new KpointTableModel(columnNames, 0);
        if (initKpts != null && initKpts.length != 0) {
            logger.debug("initial kpoints: ");
            for (int i = 0; i < initKpts.length; i++) {
                logger.debug(initKpts[i]);
                tableModel.addKpoint(initKpts[i]);
            }
        }
        jTable = new JTable(tableModel);
        JScrollPane scrpane = new JScrollPane(jTable);

        setLayout(new BorderLayout());
        add(ptext, BorderLayout.NORTH);
        add(scrpane, BorderLayout.CENTER);

        kpointGenerator = fbz.getFBZData().kpointGenerator;
        if (kpointGenerator == null)
            kpointGenerator = this;
    }

    public void saveInput(Kpoint[] kpoints, double deltak) {
        double dk = 0.02;
        if (kpointGenerator == this) {
            Utils.stop(jTable);
            logger.debug(tableModel);
            try {
                dk = Double.parseDouble(textdk.getText().trim());
            } catch (Exception exc) {
            }

            float[][] vec = fbz.getReciprocalLatticeVector();

            logger.debug("file: " + bandkptin);

            PrintWriter writer = null;
            try {
                writer = new PrintWriter(new BufferedWriter(new FileWriter(
                        bandkptin)));
                writer.println(String.valueOf(dk));
                writer.println(String.valueOf(vec[0][0]) + "  "
                        + String.valueOf(vec[1][0]) + "  "
                        + String.valueOf(vec[2][0]));
                writer.println(String.valueOf(vec[0][1]) + "  "
                        + String.valueOf(vec[1][1]) + "  "
                        + String.valueOf(vec[2][1]));
                writer.println(String.valueOf(vec[0][2]) + "  "
                        + String.valueOf(vec[1][2]) + "  "
                        + String.valueOf(vec[2][2]));
                writer.print(tableModel);
            } catch (Exception exc) {
            } finally {
                writer.flush();
                writer.close();
            }
        } else {
            kpointGenerator.saveInput(wscell.getSelectedKpoints(), dk);
        }
    }

    public void generateKpoints(Kpoint[] kpoints, double dk) {
        dk = Double.parseDouble(textdk.getText().trim());
        if (kpointGenerator == this) {
            String bandkptpl = System.getProperty("pviewer.home")
                    + System.getProperty("file.separator") + "bin"
                    + System.getProperty("file.separator") + "band_kpoint.pl";
            try {
                Runtime runtime = Runtime.getRuntime();
                Process p = runtime.exec("perl " + Utils.getPathDQ(bandkptpl)
                        + " " + Utils.getPathDQ(bandkptin));
                InputStream inputStream = p.getInputStream();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(inputStream));
                String l = "";
                while ((l = reader.readLine()) != null) {
                    logger.info(l);
                }
                reader.close();
            } catch (Exception exc) {
                exc.printStackTrace();
            }
            String foo = System.getProperty("user.dir")
                    + System.getProperty("file.separator") + "kpoint.data";
            String kpdata = fbz.getParentDirectory()
                    + System.getProperty("file.separator") + "kpoint.data";
            new File(kpdata).delete();
            new File(foo).renameTo(new File(kpdata));
        } else {
            Kpoint[] kp = tableModel.getKpoints();
            kpointGenerator.generateKpoints(kp, dk);
        }
    }

    public void kpointsInitialized() {
        logger.debug("kpoints initialized");
        for (int i = tableModel.getRowCount() - 1; i >= 0; i--) {
            tableModel.removeKpoint(i);
        }
    }

    public void kpointRemoved(Kpoint removedKPoint) {
        logger.debug("removed kpoint: " + removedKPoint);
        tableModel.removeKpoint(tableModel.getRowCount() - 1);
    }

    public void kpointAdded(Kpoint addedKpoint) {
        logger.debug("added kpoint: " + addedKpoint);
        tableModel.addKpoint(addedKpoint);
    }

    class KpointTableModel extends DefaultTableModel {
        private Logger logger = Logger.getLogger(KpointTableModel.class
                .getName());

        private Vector kpoints = new Vector();

        KpointTableModel(Object[] columnNames, int rowCount) {
            super(columnNames, rowCount);
            addTableModelListener(new TableModelListener() {
                public void tableChanged(TableModelEvent e) {
                    if (e.getColumn() == 3) {
                        int row = e.getFirstRow();
                        String sym = getValueAt(row, 3).toString();
                        ((Kpoint) kpoints.get(row)).setSymbol(sym);
                    }
                }
            });
        }

        Kpoint[] getKpoints() {
            Kpoint[] ret = new Kpoint[kpoints.size()];
            kpoints.copyInto(ret);
            return ret;
        }

        void addKpoint(Kpoint kpoint) {
            String[] sphash = kpoint.toString().split("#");
            String[] data = sphash[0].toString().split("\\s+");
            if (data.length >= 3) {
                addRow(new String[] { data[0], data[1], data[2],
                        kpoint.getSymbol() });
            }
            kpoints.addElement(kpoint);
        }

        void removeKpoint(int i) {
            removeRow(i);
            kpoints.remove(i);
        }

        public String toString() {
            String ret = "";
            for (int i = 0; i < kpoints.size(); i++) {
                ret += ((Kpoint) kpoints.get(i)).toString_bandkptpl();
                ret += System.getProperty("line.separator");
            }

            return ret;
        }

        public boolean isCellEditable(int row, int column) {
            if (column == 3) {
                return true;
            }
            return false;
        }

    }

    /**
     * ここでは使わない
     */
    public Kpoint[] getKpointsFrom(String file) {
        // TODO Auto-generated method stub
        return null;
    }

}
