/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : InputPanelPhase.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.primitiveguis;

import java.awt.event.ActionListener;
import java.util.EventListener;

import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.PopupMenuListener;

import org.apache.log4j.Logger;

import ciss.phase_viewer.inputinterface.InputInterface;

public class InputPanelPhase extends PrimitiveInputComponents implements
        PhaseInputPanelInterface {

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

    private TextFieldPhase textfield;
    private ComboBoxPhase combobox;

    private String title;
    private int unit;
    private int columns;

    public static final int NONE = 0; /* !< 単位なしを指定する. */
    public static final int LONGTIME = 1; /*
                                           * !< PHASEプログラムの実行時間を指定するための単位 (day,
                                           * hour,...)を指定する.
                                           */
    public static final int TIME = 2; /* !< PHASE内部の時間 (au_time, fs, ... ). */
    public static final int LENGTH = 3; /* !< 長さの単位を指定. */
    public static final int ENERGY = 4; /* !< エネルギーの単位を指定. */
    public static final int FORCE = 5; /* !< 力の単位を指定. */

    public static final int ANGLE = 6;

    private String[] choices;
    private String[] units_longtime = { "sec", "day", "hour", "min" };
    private String[] units_time = { "au_time", "ns", "fs", };
    private String[] units_length = { "Bohr", "Angstrom", "nm" };
    private String[] units_energy = { "Hartree", "Rydberg", "eV" };
    private String[] units_force = { "Hartree/Bohr", "eV/Angstrom" };

    private String[] units_angle = { "degree", "radian" };

    /**
     * このクラスが担当すべき入力ファイルの指定などを引数に取る.
     * 
     * @param inputSpecifications
     *            このクラスが担当すべき入力ファイルの識別子. Control.cpumax...などと記述する.
     * @param title
     *            このGUIにつけたいTitledBorder用文字列(null可).
     * @param unit
     *            単位種を指定するint値.
     * @param columns
     *            テキストフィールドのカラム数.
     * @param parent
     *            このクラスの呼び出し元. EventListenerのサブクラスをインプリメントしている必要がある.
     */
    public InputPanelPhase(String[] inputSpecifications,
            InputInterface inputinterface, String title, int unit, int columns,
            EventListener parent) {
        super(inputSpecifications, inputinterface);

        this.title = title;
        this.unit = unit;
        this.columns = columns;

        logger.debug(" from constructor 1 of ippphase.... inputSpec: "
                + inputSpecifications[0] + " isDQ? " + isDoubleQuoted);
        this.createGUI();
        this.addListeners(parent);
    }

    /**
     * このクラスが担当すべき入力ファイルの指定などを引数に取る.
     * 
     * @param inputSpecifications
     *            このクラスが担当すべき入力ファイルの識別子. Control.cpumax...などと記述する.
     * @param title
     *            このGUIにつけたいTitledBorder用文字列(null可).
     * @param unit
     *            単位種を指定するint値.
     * @param columns
     *            テキストフィールドのカラム数.
     * @param parent
     *            このクラスの呼び出し元. EventListenerのサブクラスをインプリメントしている必要がある.
     * @param 関連付けられたInputInterfacePrimitiveEntryのvalueがダブルクォートで括るべき種類のものだった場合trueをセットする
     *            .
     */
    public InputPanelPhase(String[] inputSpecifications,
            InputInterface inputinterface, String title, int unit, int columns,
            EventListener parent, boolean isDoubleQuoted) {
        super(inputSpecifications, inputinterface, isDoubleQuoted);
        this.title = title;
        this.unit = unit;
        this.columns = columns;
        logger.debug(" from constructor 2 of ippphase.... inputSpec: "
                + inputSpecifications[0] + " isDQ? " + isDoubleQuoted);
        this.createGUI();
        this.addListeners(parent);
    }

    public InputPanelPhase(String[] inputSpecifications,
            InputInterface inputinterface, String title, int unit, int columns) {
        super(inputSpecifications, inputinterface);

        this.title = title;
        this.unit = unit;
        this.columns = columns;

        logger.debug(" from constructor 3 of ippphase.... inputSpec: "
                + inputSpecifications[0] + " isDQ? " + isDoubleQuoted);
        this.createGUI();
    }

    /**
     * このクラスが保持するコンボボックスとテキストフィールドにリスナーを配備するメソッド.
     * これらはCommandインターフェースをインプリメントしているのでexecute()メソッドは必ず持っている.
     */
    public void addListeners(EventListener listener) {
        // コンボボックスは無い場合もありえる.
        if (combobox != null) {
            if (listener instanceof ActionListener) {
                combobox.addActionListener((ActionListener) listener);
            }
            if (listener instanceof PopupMenuListener) {
                combobox.addPopupMenuListener((PopupMenuListener) listener);
            }
        }
        if (listener instanceof CaretListener) {
            textfield.addCaretListener((CaretListener) listener);
        }
    }

    public void setEnabled(boolean enabled) {
        if (combobox != null) {
            combobox.setEnabled(enabled);
        }
        textfield.setEditable(enabled);
    }

    private void createGUI() {
        int pwidth;

        if (unit == NONE) {
            pwidth = columns;
        } else {
            pwidth = columns + 80;
        }

        if (unit == LONGTIME) {
            choices = (units_longtime);
        } else if (unit == TIME) {
            choices = (units_time);
        } else if (unit == LENGTH) {
            choices = (units_length);
        } else if (unit == ENERGY) {
            choices = (units_energy);
        } else if (unit == FORCE) {
            choices = (units_force);
        } else if (unit == ANGLE) {
            choices = (units_angle);
        }

        this.createTextField();
        super.add(textfield);
        if (unit != NONE) {
            this.createComboBox();
            combobox.setSize(60, 20);
            this.add(combobox);
            combobox.setSelectedIndex(combobox.getSelectedIndex());
        }

        super.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
        super.setSize(pwidth, 20);
        if (title != null) {
            super.setBorder(new TitledBorder(title));
        }
    }

    private void createTextField() {
        textfield = new TextFieldPhase(columns, inputSpecifications,
                inputInterface, isDoubleQuoted);
        String val = entry.getValue();
        logger.debug("value: " + val);
        textfield.setText(val);
    }

    private void createComboBox() {
        combobox = new ComboBoxPhase(choices, inputSpecifications,
                inputInterface, true);
        String unit = entry.getUnit();
        for (int i = 0; i < choices.length; i++) {
            if (choices[i].equalsIgnoreCase(unit)) {
                combobox.setSelectedIndex(i);
                continue;
            }
        }
        textfield.addCaretListener(new CaretListener() {
            public void caretUpdate(CaretEvent ce) {
                combobox.silentUpdate();
            }
        });

    }

    public String getValue() {
        return textfield.getText();
    }

    public JComboBox getComboBox() {
        return this.combobox;
    }

    public String getUnit() {
        return (String) combobox.getSelectedItem();
    }

    public TextFieldPhase getTextField() {
        return textfield;
    }

}
