/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : AtomConfigPanel.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.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.DecimalFormat;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.ACVCaller;
import ciss.phase_viewer.acviewer.ACVData;
import ciss.phase_viewer.acviewer.fbz.FBZ;
import ciss.phase_viewer.acviewer.fbz.FBZData;
import ciss.phase_viewer.atomcoord.Atom;
import ciss.phase_viewer.atomcoord.AtomCoords;
import ciss.phase_viewer.atomcoord.AtomEditor;
import ciss.phase_viewer.atomcoord.AtomEvent;
import ciss.phase_viewer.atomcoord.AtomList;
import ciss.phase_viewer.atomcoord.AtomListener;
import ciss.phase_viewer.atomcoord.Cell;
import ciss.phase_viewer.atomcoord.io.Exportable;
import ciss.phase_viewer.atomcoord.io.Importable;
import ciss.phase_viewer.atomcoord.symmetry.BravaisLattice;
import ciss.phase_viewer.common.ChaseFileChooser;
import ciss.phase_viewer.common.Command;
import ciss.phase_viewer.common.ConstParameters;
import ciss.phase_viewer.common.CoordsViewerBooter;
import ciss.phase_viewer.common.MyMessageBox;
import ciss.phase_viewer.common.StringConstants;
import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.inputinterface.DataManager;
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.inputinterface.InputInterfacePrimitiveEntry;
import ciss.phase_viewer.inputinterface.inputinterfacetable.InputInterfaceTableColumns;
import ciss.phase_viewer.mainpanel.Desk;
import ciss.phase_viewer.plugins.projectmanipulator.phase.PhaseConstants;
import ciss.phase_viewer.primitiveguis.ChoicePanelPhase;
import ciss.phase_viewer.primitiveguis.ChoicePanelPhaseUnit;
import ciss.phase_viewer.primitiveguis.ExportButton;
import ciss.phase_viewer.primitiveguis.ImportButton;
import ciss.phase_viewer.primitiveguis.tableforinputinterface.TableForInputInterface;
import ciss.phase_viewer.primitiveguis.tableforinputinterface.TableModelForInputInterface;
import ciss.phase_viewer.primitiveguis.tableforinputinterface.TableRightClickListener;

public class AtomConfigPanel extends JPanel implements TableModelListener,
        ActionListener, PopupMenuListener, InputInterfaceEntryChangeListener,
        InputInterfaceBlockChangeListener, AtomListener,
        TableRightClickListener, ACVCaller, Importable, Exportable {

    private static Logger logger = Logger.getLogger(AtomConfigPanel.class
            .getName());

    private InputInterface inputInterface;

    private ChoicePanelPhase p_coord;

    private String[] coordsys;

    private MyMessageBox mbox;

    private boolean validcell = true;

    private AtomCoords coords;

    private JComboBox p_cell_scheme;

    private int icellscheme;

    private JScrollPane[] scr;

    private JPanel[] pane;

    private String[] inputSpecs0;

    private String[] inputSpecs1;

    private Vector fullNameVector0;

    private Vector fullNameVector1;

    private JPanel p_cell;

    private TableModel[] tblmod_cell = new TableModel[2];

    private JCheckBox cbautoconvert;

    private JCheckBox cbautoconvertCoordSys;

    private JCheckBox cbautoconvertLength;

    private TableForInputInterface[] tfcell = new TableForInputInterface[2];

    private TableForInputInterface tfatom;

    private JComboBox cpViewer;

    private ChoicePanelPhaseUnit unitchoice;

    private String atomtag = StringConstants.phase_atom_tag;

    private int unitOld = AtomCoords.DEFAULT;

    private String[] unitChoice = { ConstParameters.NO_SELECTION, "bohr",
            "angstrom", "nm" };

    private int oldunit = AtomCoords.DEFAULT;

    public AtomConfigPanel(InputInterface inputInterface, AtomCoords coords) {
        this.inputInterface = inputInterface;
        this.coords = coords;
        init();
    }

    private void init() {
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.createUpperPanel();
        this.createCellPanel();
        this.createAtomConfigPanel();
        this.createButtons();
        this.post();
        this.inputInterface.addInputInterfaceEntryChangeListener(this);
        this.inputInterface.addInputInterfaceBlockChangeListener(this);

        createCoords();
    }

    private void post() {
        p_cell_scheme.setSelectedIndex(0);
        boolean[] btmp = new boolean[tfcell[1].getColumnCount()];
        btmp[0] = true;
        for (int i = 1; i < tfcell[1].getColumnCount(); i++) {
            btmp[i] = false;
        }
        if (tfcell[1].hasData(btmp)) {
            p_cell_scheme.setSelectedIndex(1);
        }
    }

    private JButton fbzbutton;

    private void createUpperPanel() {
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));

        String struc = "structure.";
        String[] unitspec = { struc + "unit_cell.units",
                struc + "atom_list.atoms.units" };

        JPanel punit = new JPanel();
        punit.setLayout(new BoxLayout(punit, BoxLayout.X_AXIS));
        punit.setBorder(new TitledBorder("length unit"));

        unitchoice = new ChoicePanelPhaseUnit(unitspec, inputInterface, null,
                unitChoice, this);
        JPanel pch = new JPanel();
        pch.add(unitchoice);
        punit.add(pch);

        unitchoice.getComboBox().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                if (cbautoconvertLength.isSelected())
                    autoConvertUnit();
                oldunit = unitchoice.getComboBox().getSelectedIndex();
            }
        });
        oldunit = unitchoice.getComboBox().getSelectedIndex();

        cbautoconvertLength = new JCheckBox("convert");
        punit.add(pch);
        punit.add(cbautoconvertLength);

        p.add(punit);

        JPanel pcellscheme = new JPanel();
        pcellscheme.setLayout(new BoxLayout(pcellscheme, BoxLayout.X_AXIS));
        pcellscheme.setBorder(new TitledBorder("cell scheme"));
        cbautoconvert = new JCheckBox("convert");
        String[] cell_scheme = { "a_vector,b_vector,c_vector",
                "a,b,c,alpha,beta,gamma" };
        p_cell_scheme = new JComboBox(cell_scheme);

        p_cell_scheme.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                icellscheme = p_cell_scheme.getSelectedIndex();
                logger.debug("changing cell scheme to no. " + icellscheme);
                if (cbautoconvert.isSelected()) {
                    autoConvert();
                }
                updateTableCell();
            }
        });

        pcellscheme.add(p_cell_scheme);
        pcellscheme.add(cbautoconvert);
        JPanel pcelltmp = new JPanel();
        pcelltmp.add(pcellscheme);
        p.add(pcelltmp);
        //
        // JPanel fbzpanel = new JPanel();
        // fbzpanel.setBorder(new TitledBorder("FBZ"));
        // fbzbutton = new JButton("view");
        // fbzpanel.add(fbzbutton);
        // p.add(fbzpanel);
        // fbzbutton.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent ae) {
        // bootFBZViewer();
        // }
        // });

        this.add(p);
    }

    private void bootFBZViewer() {
        coords.createCellFromTableModel(tblmod_cell);

        double[][] rlat = coords.getReciprocalLattice(inputInterface);

        if (rlat == null) {
            logger.error("invalid lattice...");
            return;
        }

        FBZData fbzdata = new FBZData();
        fbzdata.reciprocalLattice = rlat;
        fbzdata.baseDir = new File(inputInterface.getFileName()).getParent();
        fbzdata.bravaisLattice = coords.getBravaisLattice();
        FBZ fbz = new FBZ(fbzdata);
    }

    private boolean iscartOld = false;

    private void autoConvertCoordSys() {
        boolean cartNow = p_coord.getComboBox().getSelectedIndex() == 2;
        createCoords();

        coords.setUnit(oldunit);
        coords.isCart(iscartOld);

        int conv = AtomCoords.TO_INTERNAL;
        if (cartNow)
            conv = AtomCoords.TO_CART;

        coords.convert(conv, -1);
        coords.atomCoords2InputInterface(inputInterface, atomtag);
        doCell(coords);
    }

    private void autoConvertUnit() {
        createCoords();
        boolean iscart = p_coord.getComboBox().getSelectedIndex() == 2;
        coords.isCart(iscart);
        coords.setUnit(oldunit);

        int newunit = unitchoice.getComboBox().getSelectedIndex();
        int conv = AtomCoords.TO_ANG;
        if (newunit == 0 || newunit == 1)
            conv = AtomCoords.TO_BOHR;
        if (newunit == 3)
            conv = AtomCoords.TO_NM;

        coords.convert(-1, conv);

        AtomList list = coords.getAtomList();
        for (int i = 0; i < list.size(); i++)
            logger.debug(list.getAtomAt(i));

        coords.atomCoords2InputInterface(inputInterface, atomtag);
        doCell(coords);
        tfatom.revalidate();
        tfatom.repaint();
    }

    private void createCoords() {
        coords = new AtomCoords();
        coords.createCellFromTableModel(tblmod_cell);
        coords.inputInterface2AtomCoords(inputInterface, atomtag);

        int choi = unitchoice.getComboBox().getSelectedIndex();
        coords.setUnit(choi);

        String cart = (String) p_coord.getComboBox().getSelectedItem();
        if (cart.equals(coordsys[2])) {
            coords.isCart(true);
        } else {
            coords.isCart(false);
        }
    }

    private void autoConvert() {
        this.toCoords();

        createCoords();
        if (!coords.convertCell(p_cell_scheme.getSelectedIndex())) {
            logger.warn("failed to convert cell");
        }

        DecimalFormat dformat = new DecimalFormat("#.##########");

        Cell cellvec = coords.getCell(0);
        Cell cellabc = coords.getCell(1);
        try {
            if (cellvec != null) {
                String[][] dat = cellvec.getCell();
                for (int i = 0; i < 3; i++)
                    for (int j = 0; j < 3; j++)
                        tblmod_cell[0].setValueAt(
                                dformat.format(Double.parseDouble(dat[i][j])),
                                i, j + 1);
            }

            if (cellabc != null) {
                String[][] dat = cellabc.getCell();
                int count = 0;
                for (int i = 0; i < 2; i++)
                    for (int j = 0; j < 3; j++) {
                        tblmod_cell[1].setValueAt(
                                dformat.format(Double.parseDouble(dat[i][j])),
                                0, count + 1);
                        count++;
                    }
            }
        } catch (NumberFormatException e) {
            logger.error("enter a double value for cell parameters.");
            e.printStackTrace();
        }
    }

    private JScrollPane scrPane;

    private void createAtomConfigPanel() {
        String[] atmtable = new String[] { atomtag };
        inputInterface.addInputInterfaceEntryChangeListener(coords);

        JPanel p_atom_all = new JPanel();
        p_atom_all.setLayout(new BoxLayout(p_atom_all, BoxLayout.Y_AXIS));

        int[] map = { 0, 1, 2, 3, 4 };
        tfatom = new TableForInputInterface(atmtable, inputInterface, map, this);
        // test
        // tfatom = new
        // TableForInputInterface(coords,atmtable,inputInterface,map,this);

        JPanel panelAtom = new JPanel();
        panelAtom.setLayout(new BoxLayout(panelAtom, BoxLayout.Y_AXIS));
        panelAtom.add(tfatom.getPanel());

        scrPane = new JScrollPane();
        scrPane.getViewport().setView(tfatom.getPanel());
        scrPane.setPreferredSize(new Dimension(500, 150));

        scrPane.getVerticalScrollBar().setUnitIncrement(20);

        p_atom_all.add(scrPane);
        p_atom_all.setBorder(new TitledBorder("atomic coordinates"));
        this.add(p_atom_all);
        coords.setModels(tfatom.getModel(), tblmod_cell);

        tfatom.addTableRightClickListener(this);
    }

    private JTextField textselect;

    private void createButtons() {
        // add element, ionic motion, viewer buttons
        //
        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));

        JPanel p_strbtn = new JPanel();
        p_strbtn.setLayout(new FlowLayout(FlowLayout.CENTER));
        p_strbtn.setLayout(new BoxLayout(p_strbtn, BoxLayout.X_AXIS));
        // p_strbtn.setLayout(new BoxLayout(p_strbtn, BoxLayout.X_AXIS));
        // ImportButtonOld imp = new
        // ImportButtonOld("Import",tfatom,tfatom.getModel(),tfcell,tblmod_cell,coords,unitchoice.getComboBox(),this);
        // ImportButton imp2 = new
        // ImportButton("Import",tfatom,tfatom.getModel(),tfcell,tblmod_cell,unitchoice.getComboBox(),this);
        ImportButton imp2 = new ImportButton("Import", this, this);
        ExportButton exp = new ExportButton("Export", this, this);
        JButton btn = new JButton("from PHASE input");
        // ExportButton exp = new ExportButton("Export",coords,this);
        // p_strbtn.add(imp);
        p_strbtn.add(imp2);
        // p_strbtn.add(btn);
        p_strbtn.add(exp);
        // p_strbtn.add(exp);

        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                chooser();
            }
        });

        coordsys = new String[] { ConstParameters.NO_SELECTION, "internal",
                "cartesian" };
        String[] csspec = { "structure.atom_list.coordinate_system" };

        JPanel pcoordsys = new JPanel();
        pcoordsys.setLayout(new BoxLayout(pcoordsys, BoxLayout.X_AXIS));
        pcoordsys.setBorder(new TitledBorder("coordinate system"));

        p_coord = new ChoicePanelPhase(csspec, inputInterface, null, coordsys,
                this);
        p_coord.setLayout(new FlowLayout());
        p_coord.getComboBox().addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (cbautoconvertCoordSys.isSelected())
                    autoConvertCoordSys();
                coords.isCart(coordsys[p_coord.getComboBox().getSelectedIndex()]
                        .equals(coordsys[2]));
                logger.debug("isCart: " + coords.isCart());
                iscartOld = p_coord.getComboBox().getSelectedIndex() == 2;
            }
        });
        coords.isCart(coordsys[p_coord.getComboBox().getSelectedIndex()]
                .equals(coordsys[2]));
        cbautoconvertCoordSys = new JCheckBox("convert");
        pcoordsys.add(p_coord);
        pcoordsys.add(cbautoconvertCoordSys);

        iscartOld = p_coord.getComboBox().getSelectedIndex() == 2;

        p_strbtn.add(pcoordsys);
        JPanel viewerPanel = new JPanel();
        viewerPanel.setBorder(new TitledBorder("view configuration"));
        JButton viewerbtn = new JButton("View");

        String[] viewerChoice = { "internal viewer", "BioStationViewer" };
        cpViewer = new JComboBox(viewerChoice);

        viewerPanel.add(viewerbtn);
        // viewerPanel.add(cpViewer);
        p_strbtn.add(viewerPanel);

        p.add(p_strbtn);

        viewerbtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                bootViewerBooter();
            }
        });

        textselect = new JTextField(7);
        JButton btnselect = new JButton("select");
        JPanel pselect = new JPanel();
        pselect.setLayout(new BoxLayout(pselect, BoxLayout.X_AXIS));
        pselect.add(textselect);
        pselect.add(btnselect);

        btnselect.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String foo = textselect.getText();
                if (foo == null || foo.trim().length() == 0) {
                    return;
                }
                if (!Utils.isNumber(foo)) {
                    logger.error("enter a positve integer.");
                    return;
                }
                selectAtomTableRow(tfatom.getLocation(), Integer.parseInt(foo));
            }
        });

        JButton btneditatom = new JButton("edit");
        btneditatom.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int row = tfatom.getSelectedRow();
                if (row >= 0) {
                    bootAtomEditor(row);
                } else {
                    logger.info("no atom selected.");
                }
            }
        });

        JButton btnremove = new JButton("remove");
        btnremove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeSelectedAtom();
            }
        });

        JButton btnadd = new JButton("add atom");
        btnadd.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addNewAtom();
            }
        });

        JPanel paneledit = new JPanel();
        paneledit.setLayout(new BoxLayout(paneledit, BoxLayout.X_AXIS));
        paneledit.setBorder(new TitledBorder("edit atomic configuration"));

        // tmptmptmp
        // JButton btnundo = new JButton("undo");
        // btnundo.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // coords.getAtomList().undo();
        // }
        // });
        // paneledit.add(btnundo);
        // JButton btnredo = new JButton("redo");
        // btnredo.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // coords.getAtomList().redo();
        // }
        // });
        // paneledit.add(btnredo);
        // tmptmptmp

        paneledit.add(pselect);
        paneledit.add(btneditatom);
        paneledit.add(btnadd);
        paneledit.add(btnremove);
        p.add(paneledit);

        this.add(p);
    }

    public void inputInterfaceBlockChanged(InputInterfaceBlockChangeEvent e) {
    }

    private void chooser() {
        ChaseFileChooser chooser = new ChaseFileChooser(ChaseFileChooser.input,
                true);
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

        if (chooser.showDialog(this, "open") != JFileChooser.APPROVE_OPTION) {
            return;
        }

        String path = chooser.getSelectedFile().getAbsolutePath();
        DataManager manager = new DataManager(path, PhaseConstants.TABLESPEC,
                false);
        manager.parse();
        InputInterface inputFrom = manager.getInputInterface();
        inputInterface.swapBlock(InputInterface.__ROOT__, "structure",
                inputFrom, this);
        removeAll();
        init();
        revalidate();
    }

    private void bootViewerBooter() {
        String parentDir = (new File(inputInterface.getFileName())).getParent();
        Vector cv = new Vector();
        toCoords();
        cv.addElement(coords);
        logger.debug("at bootViewerBooter()");
        coords.createBravaisLattice(inputInterface,
                !BravaisLattice.isBravais(inputInterface));
        BravaisLattice bl = coords.getBravaisLattice();
        if (bl != null)
            bl.isBravais(BravaisLattice.isBravais(inputInterface));
        if (bl == null)
            logger.error("blat is null.");
        else
            logger.debug("blat is not null.");
        ACVData acvdata = new ACVData(this, cv, parentDir, inputInterface,
                atomtag);
        acvdata.setBravaisLattice(bl);

        CoordsViewerBooter cvb = new CoordsViewerBooter(acvdata,
                cpViewer.getSelectedIndex());
        try {
            cvb.boot();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // これを入れておかないとセルを二種類書き込んでしまう.
        updateInputInterface();
    }

    private void addNewAtom() {
        AtomEditor editor = new AtomEditor(inputInterface
                .getInputInterfaceTableSpecManager().getTableSpec(atomtag)
                .getTableColumns(), "edit attributes for new atom",
                new Dimension(400, 250));
        editor.addAtomListener(this);
    }

    private void removeSelectedAtom() {
        int[] rows = tfatom.getSelectedRows();
        if (rows != null) {
            for (int i = rows.length - 1; i >= 0; i--) {
                int targetRow = rows[i];
                ((DefaultTableModel) tfatom.getModel()).removeRow(targetRow);
            }
        }
    }

    class AtomEditorTable extends AtomEditor {
        private Logger logger = Logger.getLogger(AtomEditorTable.class
                .getName());

        /** Creates a new instance of AtomEditorTable */
        AtomEditorTable(InputInterfaceTableColumns[] columns, Atom atom,
                boolean newAtom, int atomIndex, String title,
                Dimension dimension) {
            super(columns, atom, newAtom, atomIndex, title, dimension);
        }

        AtomEditorTable(InputInterfaceTableColumns[] columns, String title,
                Dimension dimension) {
            super(columns, title, dimension);
        }

        protected void removeSelected() {
            removeSelectedAtom();
            dispose();
        }
    }

    private void toCoords() {
        coords = new AtomCoords();
        coords.createCellFromTableModel(tblmod_cell);
        coords.inputInterface2AtomCoords(inputInterface, atomtag);

        int choi = unitchoice.getComboBox().getSelectedIndex();
        coords.setUnit(choi);

        String cart = (String) p_coord.getComboBox().getSelectedItem();
        if (cart.equals(coordsys[2])) {
            coords.isCart(true);
        } else {
            coords.isCart(false);
        }
        coords.convert(AtomCoords.TO_CART, AtomCoords.TO_ANG);
    }

    private void createCellPanel() {
        JPanel p_cell_all = new JPanel();
        p_cell_all.setLayout(new BoxLayout(p_cell_all, BoxLayout.Y_AXIS));

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

        String uncell = "structure.unit_cell.";
        inputSpecs0 = new String[] { uncell + "a_vector", uncell + "b_vector",
                uncell + "c_vector" };
        inputSpecs1 = new String[] { uncell + "a", uncell + "b", uncell + "c",
                uncell + "alpha", uncell + "beta", uncell + "gamma" };

        fullNameVector0 = new Vector();
        for (int i = 0; i < inputSpecs0.length; i++) {
            String inp = inputSpecs0[i];
            logger.debug("inp: " + inp);
            String[] fullName = inp.split("\\.");
            fullNameVector0.addElement(fullName);
        }

        fullNameVector1 = new Vector();
        for (int i = 0; i < inputSpecs1.length; i++) {
            String inp = inputSpecs1[i];
            logger.debug("inp: " + inp);
            String[] fullName = inp.split("\\.");
            fullNameVector1.addElement(fullName);
        }

        String[] tmp = { "structure.unit_cell" };
        tfcell[0] = new TableForInputInterface(tmp, inputInterface, null, this,
                0);
        tfcell[1] = new TableForInputInterface(tmp, inputInterface, null, this,
                1);
        tfcell[0].revalidate();
        tfcell[1].revalidate();
        tfcell[0].repaint();
        tfcell[1].repaint();

        scr = new JScrollPane[2];
        pane = new JPanel[2];
        for (int i = 0; i < 2; i++) {
            tblmod_cell[i] = tfcell[i].getModel();
        }

        p_cell_all.add(p_cell);
        //
        // p_cell_all.add(pcellscheme);
        p_cell_all.setBorder(new TitledBorder("cellvector"));

        this.add(p_cell_all);
    }

    //
    private Font cellFont = new Font("Serif", Font.PLAIN, 10);

    // class CellTableCellRenderer extends DefaultTableCellRenderer {
    // public Component getTableCellRendererComponent
    // (JTable table, Object value, boolean isSelected,
    // boolean hasFocus, int row, int column) {
    // Component cell = super.getTableCellRendererComponent(table, value,
    // isSelected, hasFocus, row, column);
    // cell.setFont(cellFont);
    // if ( row%2 == 0 )
    // cell.setBackground(Color.WHITE);
    // else
    // cell.setBackground(Color.LIGHT_GRAY);
    // return cell;
    // }
    // }

    public void tableChanged(TableModelEvent e) {
        Command command = (Command) e.getSource();
        // System.out.println(command.getClass());
        command.execute(e);
    }

    public void actionPerformed(ActionEvent e) {
        Command command = (Command) e.getSource();
        command.execute(e);
    }

    public void popupMenuCanceled(PopupMenuEvent e) {
        // do nothing...
    }

    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
        // do nothing...
    }

    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
        Command command = (Command) e.getSource();
        command.execute(e);
    }

    private void updateTableCell() {
        if (p_cell == null) {
            return;
        }
        p_cell.removeAll();
        p_cell.add(tfcell[icellscheme].getPanel());
        updateInputInterface();
        revalidate();
    }

    private void updateInputInterface() {
        for (int i = 0; i < fullNameVector0.size(); i++) {
            inputInterface.selectRoot();
            String[] fullName = (String[]) fullNameVector0.get(i);
            for (int j = 0; j < fullName.length - 1; j++) {
                String ident = fullName[j];
                if (!inputInterface.selectBlock(ident)) {
                    logger.debug("couldn't select block: " + ident);
                } else {
                    logger.debug("selected block: " + ident);
                }
            }
            InputInterfacePrimitiveEntry entry = inputInterface
                    .getPrimitiveEntry(fullName[fullName.length - 1]);
            if (p_cell_scheme.getSelectedIndex() == 1) {
                entry.ignoreMe(true);
            } else {
                entry.ignoreMe(false);
            }
            inputInterface.selectRoot();
        }

        for (int i = 0; i < fullNameVector1.size(); i++) {
            inputInterface.selectRoot();
            String[] fullName = (String[]) fullNameVector1.get(i);
            for (int j = 0; j < fullName.length - 1; j++) {
                String ident = fullName[j];
                if (!inputInterface.selectBlock(ident)) {
                    logger.debug("couldn't select block: " + ident);
                } else {
                    logger.debug("selected block: " + ident);
                }
            }
            InputInterfacePrimitiveEntry entry = inputInterface
                    .getPrimitiveEntry(fullName[fullName.length - 1]);
            if (p_cell_scheme.getSelectedIndex() == 0) {
                entry.ignoreMe(true);
            } else {
                entry.ignoreMe(false);
            }
            inputInterface.selectRoot();
        }
    }

    public void inputInterfaceEntryChanged(InputInterfaceEntryChangeEvent e) {
        // do nothing...
    }

    public void inputInterfaceInitializing() {
        // do nothing...
    }

    public void inputInterfaceInitialized() {
    }

    public void atomStateChanged(AtomEvent e) {
        // Atom atom = e.getAtom();
        // int ind = e.getIndex();
        // AtomList list = new AtomList(atom,coords);
        // if ( ind < 0 ) {
        // try {
        // ind =
        // inputInterface.getInputInterfaceTable(atomtag).getTableData().size();
        // } catch(Exception exc) {
        // logger.error("atom coords not allocated?");
        // return;
        // }
        // }
        // logger.debug(e);
        // coords.atomCoords2InputInterface(inputInterface,atomtag, list, ind);
        // selectAtomTableRow(tfatom.getLocation(), ind+1);
    }

    public void tableRightClicked(Point point, String command) {
        if (command.equals("edit")) {
            bootAtomEditor(tfatom.rowAtPoint(point));
        } else if (command.equals("delete")) {
            ((DefaultTableModel) tfatom.getModel()).removeRow(tfatom
                    .rowAtPoint(point));
        } else if (command.equals("select")) {
            String res = JOptionPane.showInputDialog(Desk.getDesktop(),
                    "enter a row number", "row selection",
                    JOptionPane.INFORMATION_MESSAGE);
            if (!Utils.isNumber(res)) {
                logger.error("enter a positve integer.");
                return;
            }
            selectAtomTableRow(point, Integer.parseInt(res));
        } else if (command.equals("new")) {
            bootAtomEditor(tfatom.rowAtPoint(point), true);
        }
    }

    private void bootAtomEditor(int row) {
        bootAtomEditor(row, false);
    }

    private void bootAtomEditor(int row, boolean newAtom) {
        Atom atom = coords.inputInterface2Atom(inputInterface, atomtag, row);
        logger.debug(atom);
        AtomEditorTable editor = new AtomEditorTable(inputInterface
                .getInputInterfaceTableSpecManager().getTableSpec(atomtag)
                .getTableColumns(), atom, newAtom, row,
                "edit attributes for this atom", new Dimension(400, 250));
        editor.addAtomListener(this);
    }

    private void selectAtomTableRow(Point point, int num) {
        int old = tfatom.rowAtPoint(point);
        if (num == 0) {
            num = 1;
        }
        if (num >= tfatom.getRowCount()) {
            logger.error("exceeded max. row number.");
            return;
        }
        tfatom.setRowSelectionInterval(num - 1, num - 1);
        int rowHeight = tfatom.getRowHeight();
        int geta = rowHeight * (tfatom.getSelectedRow() - old);
        Point newPoint = new Point(point.x, point.y + geta);
        scrPane.getViewport().setViewPosition(newPoint);
        revalidate();
    }

    private void convAtomCoords(AtomCoords cds) {
        // cds.removeDupliCell();
        cds.removeIgnoreOnSaveAtoms();
        int unit = unitchoice.getComboBox().getSelectedIndex();
        int to_unit = AtomCoords.DEFAULT;
        if (unit == AtomCoords.BOHR || unit == AtomCoords.DEFAULT) {
            to_unit = AtomCoords.TO_BOHR;
        } else if (unit == AtomCoords.ANGSTROM) {
            to_unit = AtomCoords.TO_ANG;
        } else if (unit == AtomCoords.NM) {
            to_unit = AtomCoords.TO_NM;
        }

        String cart = (String) p_coord.getComboBox().getSelectedItem();
        int to_coordsys;
        if (cart.equals(coordsys[2])) {
            to_coordsys = AtomCoords.TO_CART;
            logger.debug("transforming to 'cartesian' coordinates");
        } else {
            to_coordsys = AtomCoords.TO_INTERNAL;
            logger.debug("transforming to 'internal' coordinates");
        }

        cds.isCart(true);
        cds.setUnit(AtomCoords.ANGSTROM);
        cds.convert(to_coordsys, to_unit);
    }

    public void save(AtomCoords cds) {
        coordsImported(new AtomCoords[] { cds }, null, "");
        // TableModelForTabularData mod = (TableModelForTabularData)
        // tfatom.getModel();
        // mod.clearInputInterfaceTableData();
        //
        // cds.removeDupliCell();
        // convAtomCoords(cds);
        // cds.atomCoords2InputInterface(inputInterface,atomtag);
        // cds.atomCoords2InputInterface_cell(Cell.CELL_VEC);
        // logger.info("saved coordinates to caller.");
        //
        // cds.convert(AtomCoords.TO_CART,AtomCoords.TO_ANG);
    }

    public void coordsImported(AtomCoords[] coords, String type, String fileName) {
        if (coords == null || coords.length == 0) {
            return;
        }

        coords[0].correctCellOffset();

        boolean cart = coords[0].isCart();
        Cell[] ce = coords[0].getCell();

        // coordinate systemと単位を現パネルに合わせる(ビューアーは常にcart&angstrom)
        convAtomCoords(coords[0]);

        Utils.clearTableModel(tfatom.getModel());

        // セルの処理はちょっとかっこ悪いけど差し当たり動くのでOK.
        doCell(coords[0]);

        // 原子の座標はAtomCoordsオブジェクトからInputInterfaceの該当部分差し替えメソッドで. 本来セルもここで対処すべき.
        coords[0].atomCoords2InputInterface(inputInterface, atomtag);

        // cartesian, angstrom に戻す
        // coords[0].convert(AtomCoords.TO_CART, AtomCoords.TO_ANG);
        if (cart)
            coords[0].convert(AtomCoords.TO_CART, AtomCoords.TO_ANG);
        else
            coords[0].convert(AtomCoords.TO_INTERNAL, AtomCoords.TO_ANG);

        // これを入れておかないとセルを二種類描いてしまう. かも.
        updateInputInterface();

        // tfatom.revalidate();
        // tfatom.repaint();
        tfatom.updateAll();

        inputInterface.selectRoot();
    }

    private void doCell(AtomCoords cds) {
        TableModelForInputInterface[] cellmods = new TableModelForInputInterface[2];
        for (int i = 0; i < 2; i++) {
            cellmods[i] = (TableModelForInputInterface) tfcell[i].getModel();
            cellmods[i].notifyInputInterfaceChangeListeners(false);
        }
        cds.updateTable(null, cellmods);
        for (int i = 0; i < 2; i++) {
            cellmods[i].notifyInputInterfaceChangeListeners(true);
            tfcell[i].setModel(cellmods[i]);
            tfcell[i].revalidate();
            tfcell[i].repaint();
        }
    }

    public AtomCoords[] getCoordsToExport() {
        AtomCoords coord = new AtomCoords();
        coord.createCellFromTableModel(tblmod_cell);
        coord.inputInterface2AtomCoords(inputInterface, atomtag);
        return new AtomCoords[] { coord };
    }

    // ok, nothing to do...
    public void coordsExported(AtomCoords[] coords, String type, String fileName) {
    }

}
