/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/09/15, 13:31
!  AUTHOR(S): KOGA, Junichiro
!  File : ElemPanel.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.preparationpanel.atomconfig;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;

import org.apache.log4j.Logger;

import ciss.phase_viewer.common.ElementInfo;
import ciss.phase_viewer.inputinterface.InputInterface;
import ciss.phase_viewer.inputinterface.InputInterfaceBlockChangeEvent;
import ciss.phase_viewer.inputinterface.InputInterfaceBlockChangeListener;
import ciss.phase_viewer.inputinterface.InputInterfaceEntryChangeEvent;
import ciss.phase_viewer.inputinterface.InputInterfaceEntryChangeListener;
import ciss.phase_viewer.plugins.projectmanipulator.phase.PhaseInputItems;
import ciss.phase_viewer.primitiveguis.tableforinputinterface.TableForInputInterface;
import ciss.phase_viewer.projectbrowser.ProjectInfo;
import ciss.phase_viewer.projectbrowser.ProjectManipulator;

/**
 * a panel to edit element info & specify pseudo-potential file.
 * 
 * @author
 */
public class ElemPanel extends ProjectManipulator {
    private Logger logger = Logger.getLogger(ElemPanel.class.getName());

    /** Creates a new instance of ElementPanel */
    public ElemPanel(ProjectInfo projectInfo) {
        super(projectInfo);
        setLayout(new GridLayout());
        JScrollPane scr = new JScrollPane();
        scr.getViewport().setView(new EPP(projectInfo));
        add(scr);
    }

    private boolean silent = false;

    public void init() {
    }

    public void initializeProject() {
    }

}

class EPP extends PhaseInputItems implements InputInterfaceEntryChangeListener,
        InputInterfaceBlockChangeListener {
    private Logger logger = Logger.getLogger(EPP.class.getName());

    // private Logger logger =
    // Logger.getLogger(ElementPanelPanel.class.getName());
    private TableForInputInterface tbl_elm;

    private JComboBox combo_elm;

    private JComboBox combo_num;

    private PseudoPotentialPanel pppanel;

    protected EPP(ProjectInfo projectInfo) {
        super(projectInfo);
        updateMe();
        projectInfo.getInputInterface().addInputInterfaceEntryChangeListener(
                this);
        projectInfo.getInputInterface().addInputInterfaceBlockChangeListener(
                this);
    }

    public void createGUI() {
        if (tbl_elm != null) {
            inputInterface
                    .removeInputInterfaceEntryChangeListener((InputInterfaceEntryChangeListener) tbl_elm
                            .getModel());
        }
        removeAll();

        JPanel p = new JPanel();
        p.setBorder(new TitledBorder("element info"));
        p.setLayout(new GridLayout());

        String[] elmSpec = { "structure.element_list" };

        tbl_elm = new TableForInputInterface(elmSpec, inputInterface, this);
        tbl_elm.setColumnSelectionAllowed(true);
        tbl_elm.setRowSelectionAllowed(true);
        setEditorForElementTable();

        pppanel = new PseudoPotentialPanel(projectInfo, tbl_elm.getRowCount());
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        TMLPP tlistener = new TMLPP(pppanel);
        tbl_elm.getModel().addTableModelListener(tlistener);
        JScrollPane elempane = new JScrollPane(tbl_elm.getPanel());
        p.add(elempane);

        tlistener.tableChanged(null);

        p.setPreferredSize(new Dimension(getPreferredSize().width, 150));
        pppanel.setPreferredSize(new Dimension(getPreferredSize().width, 150));
        JScrollPane pppane = new JScrollPane(pppanel);
        this.add(p);
        this.add(pppane);
        revalidate();
    }

    public void inputInterfaceEntryChanged(InputInterfaceEntryChangeEvent e) {
        if (init || e.getSource() == tbl_elm.getModel() || pppanel.updating()) {
            logger.debug("source == this");
            return;
        }
        if (e.getTag().equalsIgnoreCase("structure.atom_list.atoms")
                || e.getTag().equalsIgnoreCase("structure.element_list"))
            updateMe();
    }

    private void updateMe() {
        InputInterface inpint = projectInfo.getInputInterface();
        ElementInfo.updateElement(inpint);
        createGUI();
    }

    private boolean init = false;

    public void inputInterfaceInitializing() {
        init = true;
    }

    public void inputInterfaceInitialized() {
        init = false;
        dontCheck = true;
        updateMe();
        dontCheck = false;
    }

    class TMLPP implements TableModelListener {
        private Logger logger = Logger.getLogger(getClass().getName());

        private PseudoPotentialPanel pppanel;

        protected TMLPP(PseudoPotentialPanel pppanel) {
            this.pppanel = pppanel;
        }

        public void tableChanged(TableModelEvent e) {
            pppanel.updating(true);
            // if ( e != null ) {
            // int lastRow = e.getLastRow();
            // pppanel.updatePPPanel((String)
            // tbl_elm.getModel().getValueAt(lastRow,1),lastRow);
            // } else {
            int nrow = tbl_elm.getRowCount();
            int ncol = tbl_elm.getColumnCount();
            Vector elems = new Vector();
            int nvalid = 0;
            for (int i = 0; i < nrow; i++) {
                String elem = (String) tbl_elm.getModel().getValueAt(i, 1);
                // if ( elem != null && elem.trim().length() != 0 ) {
                elems.addElement(elem);
                // }
            }
            try {
                pppanel.updatePPPanel(elems);
            } catch (NullPointerException npe) {
                logger.debug("failed to update pseudopotential panel!");
            }
            pppanel.updating(false);
            // }
        }
    }

    private ElementInfo eI;

    private void setEditorForElementTable() {
        eI = ElementInfo.getElementInfo();
        int num_elements = eI.num_elements;
        String[] elements_list = new String[num_elements];
        String[] atomic_num_list = new String[num_elements];

        elements_list[0] = "";
        atomic_num_list[0] = "";
        for (int i = 1; i < num_elements; i++) {
            elements_list[i] = eI.getSymbolFromNumber(i);
            atomic_num_list[i] = Integer.toString(i);
            if (eI == null || eI.getSymbolFromNumber(i) == null) {
                logger.error("element info is null!!!");
                continue;
            }
            // logger.debug("got symbol: "+eI.getSymbolFromNumber(i)+" whose
            // atomic number is: "+i);
        }

        TableColumn column_elm = tbl_elm.getColumnModel().getColumn(1);
        combo_elm = new JComboBox(elements_list);
        column_elm.setCellEditor(new DefaultCellEditor(combo_elm));

        TableColumn column_num = tbl_elm.getColumnModel().getColumn(2);
        combo_num = new JComboBox(atomic_num_list);
        column_num.setCellEditor(new DefaultCellEditor(combo_num));

        combo_elm.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                String symbolSelected = (String) combo_elm.getSelectedItem();
                int row = tbl_elm.getSelectedRow();
                int col = tbl_elm.getColumnCount();

                boolean valid = !(symbolSelected == null || symbolSelected
                        .trim().length() == 0);

                if (row >= 0 && combo_elm.isPopupVisible()) {
                    inputInterface.setUpdateUndoStack(false);
                    if (valid) {
                        tbl_elm.setValueAt("", row, 2);
                        tbl_elm.setValueAt("", row, 3);
                        try {
                            int atn = eI.getNumberFromSymbol(symbolSelected);
                            tbl_elm.setValueAt(
                                    eI.getMassFromSymbol(symbolSelected), row,
                                    3);
                            tbl_elm.setValueAt(String.valueOf(eI
                                    .getNumberFromSymbol(symbolSelected)), row,
                                    2);
                        } catch (Exception ee) {
                            tbl_elm.setValueAt("", row, 2);
                            tbl_elm.setValueAt("", row, 3);
                            ee.printStackTrace();
                        }
                    } else {
                        for (int i = 0; i < col; i++) {
                            tbl_elm.setValueAt("", row, i);
                        }
                    }
                    inputInterface.setUpdateUndoStack(true);
                }

            }
        });

        combo_num.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                String numberSelected = (String) combo_num.getSelectedItem();
                int row = tbl_elm.getSelectedRow();
                int col = tbl_elm.getColumnCount();

                boolean valid = !(numberSelected == null || numberSelected
                        .trim().length() == 0);

                if (row >= 0 && combo_num.isPopupVisible()) {
                    inputInterface.setUpdateUndoStack(false);
                    if (valid) {
                        tbl_elm.setValueAt(" ", row, 1);
                        tbl_elm.setValueAt(" ", row, 3);
                        try {
                            tbl_elm.setValueAt(eI.getSymbolFromNumber(Integer
                                    .parseInt(numberSelected)), row, 1);
                            tbl_elm.setValueAt(eI.getMassFromNumber(Integer
                                    .parseInt(numberSelected)), row, 3);
                        } catch (Exception ee) {
                            logger.debug("failed to obtain symbol and mass from atomic number");
                            tbl_elm.setValueAt("", row, 1);
                            tbl_elm.setValueAt("", row, 3);
                        }
                    } else {
                        for (int i = 0; i < col; i++) {
                            tbl_elm.setValueAt("", row, i);
                        }
                    }
                    inputInterface.setUpdateUndoStack(true);
                }

            }
        });

    }

    private void updateTable() {
        tbl_elm.update(tbl_elm.getGraphics());
    }

    private boolean dontCheck = false;

    public void inputInterfaceBlockChanged(InputInterfaceBlockChangeEvent e) {
        if (e.getSource() == this || !e.getTag().equalsIgnoreCase("structure")) {
            return;
        }
        dontCheck = true;
        updateMe();
        dontCheck = false;
    }

}
