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

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import org.apache.log4j.Logger;

import ciss.phase_viewer.common.InputPanel;
import ciss.phase_viewer.common.PathSelector;
import ciss.phase_viewer.common.Utils;
import ciss.phase_viewer.mainpanel.Desk;
import ciss.phase_viewer.mainpanel.InternalFrameChase;
import ciss.phase_viewer.ssh.SshClient;
import ciss.phase_viewer.ssh.sftp.SftpClient;
import ciss.phase_viewer.ssh.terminal.Terminal;

public class HostConfigurator extends InternalFrameChase implements
        ListSelectionListener, SshClient, TableModelListener {
    private static Logger logger = Logger.getLogger(HostConfigurator.class
            .getName());

    private HostSelectorList list;

    private HostSelectorTable table;

    private JPasswordFieldHostConfigurator password;

    private CheckBoxHostConfigurator savepass;

    private CheckBoxHostConfigurator defaultHost;

    private JTabbedPane tab;

    private CaretListenerHostConfigurator caretListener;

    private ButtonListenerHostConfigurator btnlist;

    private HostInfo hostinfo;

    private Vector textfields = new Vector();

    private Vector buttons = new Vector();

    public HostConfigurator() {
        super("HostConfigurator", true, true, true, true, new Dimension(600,
                360));
        init();
    }

    public void connect(HostInfo hostinfo) {
    }

    public void disconnect() {
    }

    public void setHostInfo(HostInfo hostinfo) {
        this.hostinfo = hostinfo;
    }

    public HostInfo getHostInfo() {
        // return list.getSelectedHost();
        return table.getSelectedHost();
    }

    private void init() {
        JPanel p = new JPanel();
        // p.setLayout(new BoxLayout(p,BoxLayout.Y_AXIS));
        p.setLayout(new GridLayout(2, 1));

        JScrollPane scrollpane = new JScrollPane();
        list = new HostSelectorList();
        table = new HostSelectorTable();
        // ((DefaultTableModel)table.getModel()).addTableModelListener(this);
        caretListener = new CaretListenerHostConfigurator(table);
        btnlist = new ButtonListenerHostConfigurator(table);

        // adjustSize();
        scrollpane.getViewport().setView(table);
        JPanel ppp = new JPanel();
        ppp.add(scrollpane);
        // ppp.setBorder(new TitledBorder("list of hosts"));
        // // ppp.setLayout(new GridLayout(1,1));
        // ppp.add(scrollpane);
        JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true,
                scrollpane, createButtons2());
        p.add(split);
        // JSplitPane split = new
        // JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,connector,p);
        // split.setOneTouchExpandable(true);
        // this.getContentPane().add(split);
        // p.add(scrollpane);

        tab = new JTabbedPane();
        tab.addTab("host", createHosts());
        // tab.addTab("user", createUsers());
        tab.addTab("dir", createDirs());
        tab.addTab("ssh terminal", createTerms());
        // tab.addTab("email", createEmail());

        p.add(tab);

        // list.getJList().addListSelectionListener(this);

        JPanel pp = new JPanel();
        pp.setLayout(new BoxLayout(pp, BoxLayout.Y_AXIS));
        pp.add(p);
        pp.add(createButtons());
        this.getContentPane().add(pp);

        table.getSelectionModel().addListSelectionListener(this);
        table.getSelectionModel().setSelectionInterval(0, 0);
        revalidate();
        // list.getJList().setSelectedIndex(0);
    }

    private JPanel createButtons2() {
        JPanel p = new JPanel();
        p.setLayout(new GridLayout(4, 1));
        p.setBorder(new TitledBorder("create connection to selected host"));
        JButton tem = new JButton("ssh terminal");
        JButton tsf = new JButton("sftp client");
        p.add(tem);
        p.add(tsf);

        tem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Terminal term = new Terminal(table.getSelectedHost());
            }
        });

        tsf.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                SftpClient sfc = new SftpClient(table.getSelectedHost());
            }
        });

        return p;
    }

    private void adjustSize() {
        // int numHost = list.getJList().getModel().getSize();
        int numHost = table.getModel().getRowCount();
        int widt = (int) (this.getSize().width * 0.45);
        // Rectangle bounds = list.getJList().getCellBounds(0,0);
        // list.setPreferredSize(new Dimension(widt,(int)
        // 0.8*bounds.height*numHost));
        table.setPreferredSize(new Dimension(widt,
                table.getPreferredSize().height));
        // list.setPreferredSize(new
        // Dimension(widt,list.getPreferredSize().height));
        table.revalidate();
        // list.revalidate();
    }

    public void valueChanged(ListSelectionEvent e) {
        // HostInfo info = list.getSelectedHost();
        HostInfo info = table.getSelectedHost();
        if (info != null) {
            String pas = info.getPasswordString();

            if (pas != null) {
                password.setText(pas);
            } else {
                password.setText("");
            }

            for (int i = 0; i < buttons.size(); i++) {
                HostConfigButtons button = (HostConfigButtons) buttons.get(i);
                button.setSelected(info.getBooleanProperty(button
                        .getPropertyType()));
            }

            for (int i = 0; i < textfields.size(); i++) {
                HostConfigEditors editor = (HostConfigEditors) textfields
                        .get(i);
                editor.setValue(info.getProperty(editor.getPropertyType()));
            }

            password.setEditable(savepass.isSelected());
            btndel.setEnabled(!info.isLocalHost());

        } else {
            logger.debug("host info was null... something is wrong!");
        }
    }

    private JButton btndel;

    private JPanel createButtons() {
        JButton btncreate = new JButton("add new host");
        btndel = new JButton("delete selected host");
        JButton btnsave = new JButton("save to disk");
        JButton btnclose = new JButton("close");
        JPanel btnpanel = new JPanel();
        btnpanel.setLayout(new BoxLayout(btnpanel, BoxLayout.X_AXIS));

        btnpanel.add(btncreate);
        btnpanel.add(btndel);
        btnpanel.add(btnsave);
        btnpanel.add(btnclose);

        btncreate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addHost();
            }
        });

        btndel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                deleteHost();
            }
        });

        btnsave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                save();
            }
        });

        btnclose.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });

        return btnpanel;
    }

    private void save() {
        // list.getListofHosts().save();
        table.getListofHosts().save();
    }

    private void addHost() {
        String hostName = (String) JOptionPane.showInternalInputDialog(
                Desk.getDesktop(), "input name of host (must be unique!)",
                "new host", JOptionPane.PLAIN_MESSAGE);
        if (hostName == null || hostName.trim().length() == 0) {
            return;
        }
        if (isDupli(hostName)) {
            logger.warn("failed to add host ... found duplicate host name!");
            return;
        }

        // list.getListofHosts().addLast(new HostInfo(hostName));
        // list.recreate();
        table.addHost(new HostInfo(hostName));
        table.addRowSelectionInterval(table.getRowCount() - 1,
                table.getRowCount() - 1);
        // table.getListofHosts().addLast(new HostInfo(hostName));
        // Vector da = new Vector();
        // da.add(hostName);
        // da.add(new Boolean(false));
        // ((DefaultTableModel)table.getModel()).addRow(da);
        // //table.recreate();
        // table.repaint();
        // table.revalidate();
        // table.addRowSelectionInterval(table.getRowCount()-1,table.getRowCount()-1);
    }

    private void deleteHost() {
        // int selected = list.getSelectedIndex();
        int selected = table.getSelectedIndex();
        if (selected == 0) {
            logger.warn("can't delete localhost");
            return;
        }
        table.deleteSelectedHost();
        table.addRowSelectionInterval(table.getRowCount() - 1,
                table.getRowCount() - 1);
        // if ( selected > 0 ) {
        // table.getListofHosts().remove(selected);
        // table.recreate();
        // //this.adjustSize();
        // this.revalidate();
        // } else {
        // logger.debug("host not selected");
        // return;
        // }

    }

    private boolean isDupli(String hostName) {
        boolean ret = false;
        int n = table.getListofHosts().size();
        for (int i = 0; i < n; i++) {
            if (hostName.trim().equals(
                    (table.getListofHosts().getHostInfo(i)).getName().trim())) {
                ret = true;
                break;
            }
        }
        return ret;
    }

    private JPanel createEmail() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        InputPanelHostConfigurator smtp = new InputPanelHostConfigurator(
                "smtp_hostname", InputPanel.NONE, 15, "mail_smtphost");
        smtp.getTextField().addCaretListener(caretListener);
        textfields.add(smtp.getTextField());

        InputPanelHostConfigurator user = new InputPanelHostConfigurator(
                "sender_name", InputPanel.NONE, 15, "mail_from_user");
        InputPanelHostConfigurator fromAddres = new InputPanelHostConfigurator(
                "sender_address", InputPanel.NONE, 15, "mail_from_address");
        user.getTextField().addCaretListener(caretListener);
        fromAddres.getTextField().addCaretListener(caretListener);
        textfields.add(user.getTextField());
        textfields.add(fromAddres.getTextField());

        InputPanelHostConfigurator toAddress = new InputPanelHostConfigurator(
                "recipient_address", InputPanel.NONE, 15, "mail_to_address");
        toAddress.getTextField().addCaretListener(caretListener);
        textfields.add(toAddress.getTextField());

        CheckBoxHostConfigurator defa = new CheckBoxHostConfigurator(
                "effective on default", "mail_default");
        defa.addActionListener(btnlist);
        buttons.add(defa);

        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 3));
        p1.add(user);
        p1.add(fromAddres);
        p1.add(toAddress);

        JPanel p2 = new JPanel();
        p2.setLayout(new GridLayout(1, 3));
        p2.add(smtp);
        p2.add(new JPanel());
        p2.add(defa);

        panel.add(p1);
        panel.add(p2);

        return panel;
    }

    private JPanel createHosts() {
        JPanel panel = new JPanel();
        // panel.setLayout(new BoxLayout(panel,BoxLayout.X_AXIS));
        panel.setLayout(new GridLayout(2, 2));

        InputPanelHostConfigurator address = new InputPanelHostConfigurator(
                "address", InputPanel.NONE, 15, "address");
        address.getTextField().addCaretListener(caretListener);
        textfields.add(address.getTextField());

        InputPanelHostConfigurator username = new InputPanelHostConfigurator(
                "user name", InputPanel.NONE, 15, "username");
        username.getTextField().addCaretListener(caretListener);
        textfields.add(username.getTextField());

        JPanel ppass = new JPanel();
        ppass.setLayout(new BoxLayout(ppass, BoxLayout.X_AXIS));
        password = new JPasswordFieldHostConfigurator(15);
        password.addCaretListener(caretListener);

        savepass = new CheckBoxHostConfigurator("savepass");
        savepass.addActionListener(btnlist);
        buttons.add(savepass);

        ppass.add(password);
        ppass.add(savepass);
        ppass.setBorder(new TitledBorder("password"));

        InputPanelHostConfigurator port = new InputPanelHostConfigurator(
                "port", InputPanel.NONE, 15, "port");
        port.getTextField().addCaretListener(caretListener);
        textfields.add(port.getTextField());

        savepass.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                password.setEditable(savepass.isSelected());
                if (!savepass.isSelected()) {
                    password.setText("");
                }
            }
        });
        //
        // defaultHost = new CheckBoxHostConfigurator("set as
        // default","default");
        // buttons.add(defaultHost);
        // defaultHost.addActionListener(btnlist);
        // defaultHost.addActionListener(new ActionListener() {
        // public void actionPerformed(ActionEvent e) {
        // if ( defaultHost.isSelected() ) {
        // HostList hlist = table.getListofHosts();
        // int hostNow = table.getSelectedIndex();
        // for ( int i=0 ; i<hlist.size() ; i++ ) {
        // if ( hostNow == i ) {
        // continue;
        // }
        // hlist.getHostInfo(i).setProperty("default","false");
        // }
        // } else {
        // HostInfo loc = table.getListofHosts().getHostInfo("localhost");
        // if ( loc != null ) loc.setProperty("default","true");
        // }
        // }
        // });

        panel.add(address);
        panel.add(username);
        panel.add(ppass);
        panel.add(port);
        // panel.add(defaultHost);

        return panel;
    }

    private JTextField tfbase;

    private JTextField tfbin;

    private JTextField tfmpi;

    private JTextField tfjava;

    private JPanel createDirs() {
        JPanel panel = new JPanel();
        // panel.setLayout(new BoxLayout(panel,BoxLayout.X_AXIS));
        panel.setLayout(new GridLayout(2, 2));

        PathSelectorHostConfigurator basedir = new PathSelectorHostConfigurator(
                "base directory", 12, "basedir", this);
        basedir.getTextField().addCaretListener(caretListener);
        JPanel p1 = new JPanel();
        p1.add(basedir);
        textfields.add(basedir.getTextField());
        tfbase = basedir.getTextField();

        PathSelectorHostConfigurator bindir = new PathSelectorHostConfigurator(
                "bin directory", 12, "bindir", this);
        bindir.getTextField().addCaretListener(caretListener);
        JPanel p2 = new JPanel();
        p2.add(bindir);
        textfields.add(bindir.getTextField());
        tfbin = bindir.getTextField();

        PathSelectorHostConfigurator mpidir = new PathSelectorHostConfigurator(
                "MPI directory", 12, "mpidir", this);
        mpidir.getTextField().addCaretListener(caretListener);
        JPanel p3 = new JPanel();
        p3.add(mpidir);
        textfields.add(mpidir.getTextField());
        tfmpi = mpidir.getTextField();

        PathSelectorHostConfigurator javadir = new PathSelectorHostConfigurator(
                "java directory", 12, "javadir", this);
        javadir.getTextField().addCaretListener(caretListener);
        JPanel p4 = new JPanel();
        p4.add(javadir);
        textfields.add(javadir.getTextField());
        tfjava = javadir.getTextField();

        panel.add(p1);
        panel.add(p2);
        panel.add(p3);
        panel.add(p4);

        JPanel pret = new JPanel();
        pret.setLayout(new BorderLayout());
        pret.add(panel, BorderLayout.CENTER);

        JButton btndefault = new JButton("enter default");
        JPanel pbtn = new JPanel();
        pbtn.setLayout(new GridLayout(4, 1));
        pbtn.add(new JPanel());
        pbtn.add(new JPanel());
        pbtn.add(btndefault, BorderLayout.NORTH);
        pbtn.add(new JPanel());
        pret.add(pbtn, BorderLayout.EAST);

        btndefault.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub
                doEnterDefault();
            }
        });
        return pret;
    }

    private void doEnterDefault() {
        if (!table.getSelectedHost().isLocalHost()) {
            String str = JOptionPane
                    .showInternalInputDialog(
                            this,
                            "enter the installation location of PHASE \n for the remote host (ex: /opt/PHASE)",
                            "", JOptionPane.DEFAULT_OPTION);
            if (str != null && str.trim().length() != 0) {
                String basedir = "/home/" + System.getProperty("user.name")
                        + "/phase-viewer-projects";
                String bindir = str + "/bin";
                String mpidir = str + "/mpi";
                String javadir = str + "/_jvm";
                tfbase.setText(basedir);
                tfbin.setText(bindir);
                tfmpi.setText(mpidir);
                tfjava.setText(javadir);
            }
        } else {
            String bindir = System.getProperty("pviewer.home")
                    + System.getProperty("file.separator") + "bin";
            String mpidir = "";
            if (!Utils.isWindows())
                mpidir = System.getProperty("pviewer.home")
                        + System.getProperty("file.separator") + "mpi";
            String javadir = System.getProperty("pviewer.home")
                    + System.getProperty("file.separator") + "_jvm";
            tfbin.setText(bindir);
            tfmpi.setText(mpidir);
            tfjava.setText(javadir);
        }
    }

    private JPanel createTerms() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        CheckBoxHostConfigurator cbxforward = new CheckBoxHostConfigurator(
                "enable X forwarding", "xforwarding");
        cbxforward.addActionListener(btnlist);
        buttons.add(cbxforward);

        CheckBoxHostConfigurator cbantialias = new CheckBoxHostConfigurator(
                "enable anti-aliasing", "antialiasing");
        cbantialias.addActionListener(btnlist);
        buttons.add(cbantialias);

        panel.add(cbxforward);
        panel.add(cbantialias);
        return panel;
    }

    public void tableChanged(TableModelEvent arg0) {
        HostInfo info = table.getSelectedHost();
        if (info != null) {
            String pas = info.getPasswordString();

            if (pas != null) {
                password.setText(pas);
            } else {
                password.setText("");
            }

            for (int i = 0; i < buttons.size(); i++) {
                HostConfigButtons button = (HostConfigButtons) buttons.get(i);
                button.setSelected(info.getBooleanProperty(button
                        .getPropertyType()));
            }

            for (int i = 0; i < textfields.size(); i++) {
                HostConfigEditors editor = (HostConfigEditors) textfields
                        .get(i);
                editor.setValue(info.getProperty(editor.getPropertyType()));
            }

            password.setEditable(savepass.isSelected());
            btndel.setEnabled(!info.isLocalHost());

        } else {
            logger.debug("host info was null... something is wrong!");
        }
    }

}

class TextFieldHostConfigurator extends JTextField implements HostConfigEditors {
    private String type = "name";

    protected TextFieldHostConfigurator(String title, int collen, String type) {
        super(title, collen);
        this.type = type;
    }

    public String getPropertyType() {
        return type;
    }

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

    public void setValue(String value) {
        super.setText(value);
    }
}

class CheckBoxHostConfigurator extends JCheckBox implements HostConfigButtons {
    private String type = "password";

    protected CheckBoxHostConfigurator(String type) {
        super();
        this.type = type;
    }

    protected CheckBoxHostConfigurator(String title, String type) {
        super(title);
        this.type = type;
    }

    public String getPropertyType() {
        return type;
    }

    public boolean isSelected() {
        return super.isSelected();
    }

    public void setSelected(boolean selected) {
        super.setSelected(selected);
    }
}

class InputPanelHostConfigurator extends InputPanel {
    protected InputPanelHostConfigurator(String title, int unit, int collen,
            String type) {
        super(title, unit, collen, new TextFieldHostConfigurator("", collen,
                type), true);
    }

}

class PathSelectorHostConfigurator extends PathSelector {
    protected PathSelectorHostConfigurator(String title, int collen,
            String type, SshClient parent) {
        super(title, collen, new TextFieldHostConfigurator("", collen, type),
                true);
        super.setSshClient(parent);
    }
}

class JPasswordFieldHostConfigurator extends JPasswordField implements
        HostConfigEditors {
    protected JPasswordFieldHostConfigurator(int collen) {
        super(collen);
    }

    public String getPropertyType() {
        return "password";
    }

    public String getValue() {
        char[] pass = super.getPassword();
        return new String(pass);
    }

    public void setValue(String pass) {
    }

}

class CaretListenerHostConfigurator implements CaretListener {
    private static Logger logger = Logger
            .getLogger(CaretListenerHostConfigurator.class.getName());

    private HostSelector parent;

    private HostList list;

    private String tag;

    protected CaretListenerHostConfigurator(HostSelector parent) {
        this.parent = parent;
        this.list = parent.getListofHosts();
    }

    public void caretUpdate(CaretEvent e) {
        HostConfigEditors editor = (HostConfigEditors) e.getSource();
        int selected = parent.getSelectedIndex();
        if (selected < 0) {
            // logger.warn("not a valid index");
            return;
        }

        HostInfo info = list.getHostInfo(selected);
        String type = editor.getPropertyType();
        String value = editor.getValue();
        if (type.equals("password")) {
            info.setPasswordString(value);
        } else {
            info.setProperty(type, value);
        }

        logger.debug("updated host info no. " + selected);
        logger.debug("value is: " + value);
    }

}

class ButtonListenerHostConfigurator implements ActionListener {
    private static Logger logger = Logger
            .getLogger(ButtonListenerHostConfigurator.class.getName());

    private HostSelector parent;

    private HostList list;

    protected ButtonListenerHostConfigurator(HostSelector parent) {
        this.parent = parent;
        this.list = parent.getListofHosts();
    }

    public void actionPerformed(ActionEvent e) {
        HostConfigButtons btn = (HostConfigButtons) e.getSource();
        int selected = parent.getSelectedIndex();
        if (selected < 0) {
            logger.warn("not a valid index");
            return;
        }

        HostInfo info = list.getHostInfo(selected);

        String type = btn.getPropertyType();
        info.setProperty(type, btn.isSelected());

        logger.debug("updated host info " + selected);
        logger.debug("value is: " + btn.isSelected());
    }

}
