/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2007/04/13 11:35:37
!  AUTHOR(S): KOGA, Junichiro
!  File : CellPanel.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.viewer.edit;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
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.DefaultTableCellRenderer;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.ConfigData;
import ciss.phase_viewer.acviewer.ConfigDataUpdateEvent;
import ciss.phase_viewer.acviewer.CoordsViewerInterface;
import ciss.phase_viewer.acviewer.MainPanel;
import ciss.phase_viewer.acviewer.operations.EnlargeCell;
import ciss.phase_viewer.atomcoord.Atom;
import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.atomcoord.Cell;
import ciss.phase_viewer.common.ExcelAdapter;
import ciss.phase_viewer.common.InputPanel;

public class CellPanel extends JPanel implements TableModelListener, ConfigData {
    private Logger logger = Logger.getLogger(CellPanel.class.getName());
    private CoordsViewerInterface parent;

    private JTable tbl_cell;

    private JButton enlargeButton;
    private InputPanel ipenlargeA;
    private InputPanel ipenlargeB;
    private InputPanel ipenlargeC;

    private final String one = "1";

    private Atom[] origAtoms;
    private Cell origCell;

    private boolean updateCell = true;

    private EnlargeCell enlargeCell;

    public CellPanel(CoordsViewerInterface parent) {
        this.parent = parent;

        enlargeCell = new EnlargeCell(parent.getFramesAC(), (MainPanel) parent);

        init();
    }

    public void tableChanged(TableModelEvent e) {
        if (!updateCell) {
            return;
        }

        Cell cell = getCell();
        if (cell == null) {
            return;
        }
        AtomCoords coords = parent.getCD().getAtomCoords();
        coords.setCell(cell);
        coords.getAtomList().setUndoCount(1);
        parent.getCD().setCoords(coords);
    }

    private Cell getCell() {
        String[] avec = new String[3];
        String[] bvec = new String[3];
        String[] cvec = new String[3];
        for (int i = 0; i < 3; i++) {
            avec[i] = (String) tbl_cell.getValueAt(0, i + 1);
            bvec[i] = (String) tbl_cell.getValueAt(1, i + 1);
            cvec[i] = (String) tbl_cell.getValueAt(2, i + 1);
            try {
                Double.parseDouble(avec[i]);
                Double.parseDouble(bvec[i]);
                Double.parseDouble(cvec[i]);
            } catch (NumberFormatException nfe) {
                logger.error("cell parameter must be a double value.");
                return null;
            } catch (NullPointerException npe) {
                logger.error("one of the value for the cell parameters was invalid.");
                return null;
            }
        }

        return new Cell(avec, bvec, cvec);
    }

    private JCheckBox cbactonall;

    private void init() {
        createOrig();
        parent.getCD().register(this);

        String[] colname_cell = { "unit cell", "x", "y", "z" };
        String[][] celldata = { { "a-axis", "", "", "" },
                { "b-axis", "", "", "" }, { "c-axis", "", "", "" } };
        tbl_cell = new JTable(celldata, colname_cell);
        tbl_cell.setColumnSelectionAllowed(true);
        tbl_cell.setRowSelectionAllowed(true);
        JScrollPane scrPaneCell = new JScrollPane();
        scrPaneCell.getViewport().setView(tbl_cell);
        scrPaneCell.setPreferredSize(new Dimension(350, 70));

        ExcelAdapter ea_cell = new ExcelAdapter(tbl_cell);

        DefaultTableCellRenderer dtcr = new DefaultTableCellRenderer();
        dtcr.setHorizontalAlignment(JLabel.CENTER);
        JTextField tf = new JTextField("");
        tf.setEditable(false);
        DefaultCellEditor dce = new DefaultCellEditor(tf);
        tbl_cell.getColumnModel().getColumn(0).setCellRenderer(dtcr);
        tbl_cell.getColumnModel().getColumn(0).setCellEditor(dce);

        Cell[] cell = parent.getCD().getAtomCoords().getCell();
        if (cell != null && cell.length != 0) {
            double[][] data = cell[0].getDouble();
            try {
                for (int i = 0; i < 3; i++) {
                    for (int j = 0; j < 3; j++) {
                        tbl_cell.getModel().setValueAt(
                                String.valueOf(data[i][j]), i, j + 1);
                    }
                }
            } catch (Exception exc) {
                logger.error("unable to show cell data...");
                exc.printStackTrace();
            }
        }

        JPanel patconfig_cell = new JPanel();
        patconfig_cell.setBorder(new TitledBorder("cell"));
        patconfig_cell.add(scrPaneCell);

        JPanel patconfig_enlarge = new JPanel();
        patconfig_enlarge.setLayout(new BoxLayout(patconfig_enlarge,
                BoxLayout.X_AXIS));

        enlargeButton = new JButton("apply");
        JButton setButton = new JButton("set current structure as base");
        cbactonall = new JCheckBox("act on all frames");
        cbactonall.setSelected(true);

        ipenlargeA = new InputPanel("a-axis", 0, 5);
        ipenlargeB = new InputPanel("b-axis", 0, 5);
        ipenlargeC = new InputPanel("c-axis	", 0, 5);
        JPanel textPanel = new JPanel();
        textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.X_AXIS));
        textPanel.add(ipenlargeA);
        textPanel.add(ipenlargeB);
        textPanel.add(ipenlargeC);

        patconfig_enlarge.add(cbactonall);
        patconfig_enlarge.add(enlargeButton);
        patconfig_enlarge.add(setButton);
        ipenlargeA.setValue(one);
        ipenlargeB.setValue(one);
        ipenlargeC.setValue(one);

        this.add(patconfig_cell);
        JPanel enlargePanel = new JPanel();
        enlargePanel.setLayout(new BoxLayout(enlargePanel, BoxLayout.Y_AXIS));
        enlargePanel.add(textPanel);
        enlargePanel.add(patconfig_enlarge);
        enlargePanel.setBorder(new TitledBorder("supercell"));
        this.add(enlargePanel);

        enlargeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                doEnlarge();
            }
        });

        setButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                createOrig();
            }
        });

        cbactonall.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enlargeCell.setDoAllFrames(cbactonall.isSelected());
            }
        });

        enlargeCell.setDoAllFrames(true);
        tbl_cell.getModel().addTableModelListener(this);
    }

    private void createOrig() {
        enlargeCell.recreateOrig();
    }

    int prevA = 1;
    int prevB = 1;
    int prevC = 1;

    private void doEnlarge() {
        int a = 1;
        int b = 1;
        int c = 1;
        double[][] dCell = new double[3][3];
        try {
            a = Integer.parseInt(ipenlargeA.getValue());
            b = Integer.parseInt(ipenlargeB.getValue());
            c = Integer.parseInt(ipenlargeC.getValue());
        } catch (NumberFormatException nfe) {
            logger.error("enter an integer value!");
            return;
        }

        if (prevA == 1 && prevB == 1 && prevC == 1) {
            enlargeCell.recreateOrig();
        }
        enlargeCell.doEnlarge(a, b, c);

        updateCell = false;
        double[][] newCell = parent.getCD().getCell();
        for (int i = 0; i < 3; i++) {
            tbl_cell.getModel().setValueAt(String.valueOf(newCell[0][i]), 0,
                    i + 1);
            tbl_cell.getModel().setValueAt(String.valueOf(newCell[1][i]), 1,
                    i + 1);
            tbl_cell.getModel().setValueAt(String.valueOf(newCell[2][i]), 2,
                    i + 1);
        }
        updateCell = true;
        prevA = a;
        prevB = b;
        prevC = c;
    }

    public void configDataUpdate() {
        Cell cell = parent.getCD().getAtomCoords().getCell(0);
        if (cell != null) {
            updateCell = false;
            String[][] newCell = cell.getCell();
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    tbl_cell.getModel().setValueAt(newCell[i][j], i, j + 1);
                }
            }
            updateCell = true;
        }
    }

    public void configDataUpdate(boolean rescaleOnUpdate,
            ConfigDataUpdateEvent e) {
        configDataUpdate();
    }

    public boolean needsUpdate() {
        return true;
    }

}
