/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/09/15, 16:22
!  AUTHOR(S): KOGA, Junichiro
!  File : PseudoPotentialPanel.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.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;

import org.apache.log4j.Logger;

import ciss.phase_viewer.common.ChaseFileChooser;
import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.file.ChaseFile;
import ciss.phase_viewer.file.ChaseFileManager;
import ciss.phase_viewer.inputinterface.InputInterface;
import ciss.phase_viewer.inputinterface.InputInterfacePrimitiveEntry;
import ciss.phase_viewer.projectbrowser.ProjectInfo;
import ciss.phase_viewer.settings.GlobalProperties;
import ciss.phase_viewer.settings.PropertiesManager;

/**
 * a jpanel to show & edit pseudo-potential info. paths to pp-files are saved
 * automatically.
 * 
 * @author
 */
public class PseudoPotentialPanel extends JPanel {
    private Logger logger = Logger.getLogger(PseudoPotentialPanel.class
            .getName());
    private ProjectInfo projectInfo;

    private Vector ppselectors = new Vector();
    private boolean setTitle = true;
    private int numPP = 1;

    /**
     * Creates a new instance of PseudoPotentialPanel
     * 
     * @param projectInfo
     *            a ProjectInfo object, which contains various information
     *            regarding the target project.
     */
    public PseudoPotentialPanel(ProjectInfo projectInfo, int numPP) {
        this.projectInfo = projectInfo;
        this.numPP = numPP;
        setBorder(new TitledBorder("specify pseudo potential file (s)"));
        setLayout(new GridLayout());
        init();
    }

    protected void updatePPPanel(Vector elems) throws NullPointerException {
        for (int i = 0; i < elems.size(); i++) {
            String elename = (String) elems.elementAt(i);
            PseudoPotentialSelector pps = (PseudoPotentialSelector) ppselectors
                    .elementAt(i);
            if (pps.getElementName() == null
                    || !pps.getElementName().equals(elename)) {
                pps.clear();
                pps.setElementName(elename);
            }
        }
    }

    protected void updatePPPanel(String elem, int index) {
        PseudoPotentialSelector pps = (PseudoPotentialSelector) ppselectors
                .elementAt(index);
        if (pps.getElementName() == null || !pps.getElementName().equals(elem)) {
            pps.setElementName(elem);
        }
    }

    private boolean updating = false;

    /**
     * このパネルが「更新中」ならばtrueを返す.
     * 
     * @return パネルのデータが変更中ならtrue.
     */
    protected boolean updating() {
        return this.updating;
    }

    /**
     * このGUIの内容が変更中であるかどうかをセット. テーブルモデルリスナーに呼ばれる.
     * 
     * @param updating
     *            更新中にしたい場合これをtrueとする. 終わったらfalseをセット.
     */
    protected void updating(boolean updating) {
        this.updating = updating;
    }

    private void init() {

        JScrollPane scrollPane = new JScrollPane();

        File ppDir = new File(System.getProperty("pviewer.home")
                + System.getProperty("file.separator") + "pp");
        boolean ppDirExists = ppDir.exists();
        logger.debug("ppdir: " + ppDir + " exsists? " + ppDirExists);
        JPanel panel0 = new JPanel();
        panel0.setLayout(new BoxLayout(panel0, BoxLayout.Y_AXIS));

        JLabel lno = new JLabel("no");
        JLabel lelem = new JLabel("element");
        JLabel pp = new JLabel("pp file name");
        JLabel bfc = new JLabel("select by filechooser");

        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gc = new GridBagConstraints();

        gc.weightx = 0.2;
        gc.ipadx = 40;
        panel.add(lno, gc);

        gc.weightx = 0.1;
        gc.ipadx = 0;
        lelem.setPreferredSize(new Dimension(50, 25));
        panel.add(lelem, gc);

        gc.ipadx = 40;
        gc.weightx = 0.5;
        panel.add(pp, gc);

        gc.ipadx = 0;
        gc.weightx = 0.2;
        panel.add(bfc, gc);

        panel0.add(panel);

        for (int i = 0; i < numPP; i++) {
            PseudoPotentialSelector pps = new PseudoPotentialSelector(
                    (new Integer(i + 1)).toString());
            panel0.add(pps);
            ppselectors.addElement(pps);
        }

        scrollPane.getViewport().setView(panel0);
        this.add(scrollPane);
    }

    /**
     * a class representing a 'pseudo-potential selector'.
     */
    class PseudoPotentialSelector extends JPanel {
        private InputInterface inputInterface;
        private String ID;
        private String element;

        private JLabel labelElement;
        private JComboBox ppCandidate;
        private JButton fileChooser;

        private File ppDir;

        private String NO_CANDIDATE = Utils.NO_CANDIDATE;

        private ChaseFileManager cfManager;

        private boolean isLDA = false;
        private boolean isPAW = false;

        protected PseudoPotentialSelector(String ID) {
            this.ID = ID;
            this.inputInterface = projectInfo.getInputInterface();
            GlobalProperties gp = PropertiesManager
                    .getGlobalProperties(PropertiesManager.PROPERTIES_PVIEWER);
            // String strpp = System.getProperty("pviewer.home") +
            // System.getProperty("file.separator") + gp.getProperty("ppdir");

            cfManager = projectInfo.getChaseFileManager();
            logger.debug("proj. info associated to ChaseFileManager: "
                    + cfManager.getProjectInfo());
            String strpp = Utils.getDefaultPPDir();
            ppDir = new File(strpp);

            setLayout(new GridBagLayout());
            init();
            if (cfManager == null) {
                setElementName(null);
                logger.error("invalid chasefilemanager");
            } else {
                ChaseFile[] pots = cfManager.getFiles("F_POT(.+)");
                if (pots != null && pots.length >= Integer.parseInt(ID)) {
                    logger.debug("ppname at this point "
                            + pots[Integer.parseInt(ID) - 1].getFileName());
                    String ppName = pots[Integer.parseInt(ID) - 1]
                            .getFileName();
                    if (!(ppName == null || ppName.length() == 0)) {
                        String pdir = pots[Integer.parseInt(ID) - 1]
                                .getRelativePath();
                        if (pdir != null && new File(pdir).exists()
                                && new File(pdir).isDirectory()) {
                            ppDir = new File(projectInfo.getProjectDirectory()
                                    + System.getProperty("file.separator")
                                    + pdir);
                            logger.debug("ppDir : " + ppDir.getAbsolutePath());
                        }
                        String elname = ppName.split("_")[0];
                        setElementName(elname, ppName);
                    }
                }
                ppCandidate.setToolTipText("Directory : "
                        + ppDir.getAbsolutePath());
            }
        }

        private void init() {
            inputInterface.selectRoot();
            inputInterface.selectBlock("accuracy");
            InputInterfacePrimitiveEntry xc = inputInterface
                    .getPrimitiveEntry("xctype");
            if (xc != null) {
                isLDA = xc.getValue().toLowerCase().startsWith("lda");
            }
            InputInterfacePrimitiveEntry paw = inputInterface
                    .getPrimitiveEntry("paw");
            if (paw == null || paw.getValue().length() == 0)
                paw = inputInterface.getPrimitiveEntry("paw_switch");
            if (paw != null)
                isPAW = Utils.getBool(paw.getValue());

            GridBagConstraints gc = new GridBagConstraints();

            JLabel labelID = new JLabel(ID);
            labelElement = new JLabel(element);

            ppCandidate = new JComboBox();
            ppCandidate.setEnabled(false);
            ppCandidate.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (ppCandidate.getSelectedItem() != null
                            && !ppCandidate.getSelectedItem().toString()
                                    .equals(NO_CANDIDATE)) {
                        updateFileInfo();
                    }
                }
            });

            fileChooser = new JButton("choose");
            // fileChooser.setEnabled(false);
            fileChooser.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    selectPPFromChooser();
                }
            });

            JPanel panel1 = new JPanel();
            panel1.setLayout(new GridLayout());
            panel1.add(labelID);

            JPanel panel2 = new JPanel();
            panel2.setLayout(new GridLayout());
            panel2.add(labelElement);
            labelElement.setPreferredSize(new Dimension(20, 25));

            JPanel panel3 = new JPanel();
            panel3.setLayout(new GridLayout());
            panel3.add(ppCandidate);

            JPanel panel4 = new JPanel();
            panel4.setLayout(new GridLayout());
            panel4.add(fileChooser);

            gc.weightx = 0.2;
            gc.ipadx = 40;
            gc.insets = new Insets(0, 20, 0, 30);
            add(panel1, gc);

            gc.insets = new Insets(0, 0, 0, 0);
            add(panel2, gc);

            // gc.fill = GridBagConstraints.HORIZONTAL;
            gc.weightx = 0.5;
            ppCandidate.setPreferredSize(new Dimension(130, 25));
            add(ppCandidate, gc);

            gc.weightx = 0.2;
            add(panel4, gc);
        }

        protected void clear() {
            setElementName("");
            ChaseFile[] pots = cfManager.getFiles("F_POT(.+)");
            if (pots != null && pots.length >= Integer.parseInt(ID)) {
                cfManager.removeFile(pots[Integer.parseInt(ID) - 1]);
            }
            // cfManager.save();
        }

        protected String getElementName() {
            return this.element;
        }

        private void setElementName(String elementName, String ppName) {
            this.element = elementName;
            labelElement.setText(elementName);
            String[] ppcands = getPPChoices(elementName);

            ppCandidate.removeAllItems();
            for (int i = 0; i < ppcands.length; i++) {
                ppCandidate.addItem(ppcands[i]);
            }
            String pptype = "gga";
            if (isLDA) {
                pptype = "lda";
            }
            String[] pptype2 = new String[] { "us", "nc" };
            if (isPAW)
                pptype2 = new String[] { "paw" };
            if (ppName != null) {
                for (String pp : ppcands)
                    if (pp.equals(ppName)) {
                        ppCandidate.setSelectedItem(pp);
                        return;
                    }
            }
            for (int i = 0; i < ppcands.length; i++) {
                if (ppcands[i].indexOf(pptype) != -1) {
                    for (int j = 0; j < pptype2.length; j++)
                        if (ppcands[i].indexOf(pptype2[j]) != -1) {
                            ppCandidate.setSelectedIndex(i);
                            break;
                        }
                }
            }
        }

        protected void setElementName(String elementName) {
            this.setElementName(elementName, null);
        }

        private void selectPPFromChooser() {
            ChaseFileChooser chooser = new ChaseFileChooser(ChaseFileChooser.pp);

            chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
            chooser.setDialogTitle("select pseudopotential file");
            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) {
                return;
            }
            File pppath = chooser.getSelectedFile().getAbsoluteFile();

            ppCandidate.removeAllItems();
            ppDir = pppath.getParentFile();
            ppCandidate
                    .setToolTipText("Directory : " + ppDir.getAbsolutePath());
            ppCandidate.addItem(pppath.getName());
            revalidate();
        }

        private void updateFileInfo() {
            logger.debug("pp-filename: " + ppCandidate.getSelectedItem());

            // String pp_dire =
            // ciss.phase_viewer.common.Utils.getDefaultPPDir();
            String pp_dire = ppDir.getAbsolutePath();
            String projdir = projectInfo.getProjectDirectory();
            String dir = Utils.getRelativePath(projdir, pp_dire);
            ChaseFile[] pots = cfManager.getFiles("F_POT(.+)");
            if (pots == null || pots.length < Integer.parseInt(ID)) {
                logger.debug("no existing pp...");
                logger.debug("adding: " + dir + "/"
                        + (String) ppCandidate.getSelectedItem());
                cfManager.addFile(dir, "F_POT(" + Integer.parseInt(ID) + ")",
                        (String) ppCandidate.getSelectedItem());
            } else {
                pots[Integer.parseInt(ID) - 1].update("filename",
                        (String) ppCandidate.getSelectedItem());
                pots[Integer.parseInt(ID) - 1].update(ChaseFile.RELATIVE_PATH,
                        dir);
            }
            cfManager.save();
        }

        private String[] getPPChoices(String element) {
            String[] cands = Utils.getPPCandidates(element,
                    ppDir.getAbsolutePath());
            ppCandidate.setEnabled(true);
            if (cands[0].equals(NO_CANDIDATE))
                ppCandidate.setEnabled(false);
            return cands;
        }

    }
}
