package org.jivesoftware.spark.plugin.otr.pref;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.JTextField;

import net.java.otr4j.OtrKeyManager;
import net.java.otr4j.session.SessionID;

import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.spark.SparkManager;

import org.jivesoftware.spark.plugin.otr.OTRManager;
import org.jivesoftware.spark.plugin.otr.util.OTRProperties;
import org.jivesoftware.spark.plugin.otr.util.OTRResources;
import org.jxmpp.jid.EntityFullJid;

/**
 * OTR preference panel for Spark Preferences
 * 
 * @author Bergund Holger
 */
public class OTRPrefPanel extends JPanel {
    private final OTRManager _manager;
    private JCheckBox _enableOTR;
    private JCheckBox _closeSessionOff;
    private JCheckBox _closeSessionOnWindowClose;
    private JLabel _currentKeyLabel;
    private JButton _renewPrivateKey;
    private OTRKeyTable _keytable;
    private JTextField _privateKey;
    private final OtrKeyManager _keyManager;
    private final OTRProperties _properties;

    public OTRPrefPanel() {
        _manager = OTRManager.getInstance();
        _keyManager = _manager.getKeyManager();
        _properties = OTRProperties.getInstance();
        setLayout(new GridBagLayout());
        init();
        buildGUI();
        OtrEnableSwitch();
    }

    private void OtrEnableSwitch() {
        _closeSessionOff.setEnabled(_enableOTR.isSelected());
        _closeSessionOnWindowClose.setEnabled(_enableOTR.isSelected());
        _renewPrivateKey.setEnabled(_enableOTR.isSelected());
        _keytable.setEnabled(_enableOTR.isSelected());
    }

    private void init() {
        _enableOTR = new JCheckBox();
        _enableOTR.setText(OTRResources.getString("otr.enable"));
        _enableOTR.setSelected(_properties.getIsOTREnabled());

        _enableOTR.addActionListener(e -> OtrEnableSwitch());

        _closeSessionOff = new JCheckBox();
        _closeSessionOff.setText(OTRResources.getString("otr.close.session.on.contact.off"));
        _closeSessionOff.setSelected(_properties.getOTRCloseOnDisconnect());

        _closeSessionOnWindowClose = new JCheckBox();
        _closeSessionOnWindowClose.setText(OTRResources.getString("otr.close.session.on.window.close"));
        _closeSessionOnWindowClose.setSelected(_properties.getOTRCloseOnChatClose());

        _currentKeyLabel = new JLabel();
        _currentKeyLabel.setText(OTRResources.getString("current.priv.key"));

        _renewPrivateKey = new JButton();
        _renewPrivateKey.setText(OTRResources.getString("renew.current.key"));
        _renewPrivateKey.addActionListener(e -> {
            EntityFullJid userJid = SparkManager.getConnection().getUser();
            SessionID mySession = new SessionID(userJid.toString(), "no one", "prpl-jabber");
            _manager.getKeyManager().generateLocalKeyPair(mySession);
            _privateKey.setText(getCurrentLocalKey());
        });

        _privateKey = new JTextField();
        _privateKey.setEditable(false);
        _privateKey.setText(getCurrentLocalKey());

        _keytable = new OTRKeyTable();

        loadRemoteKeys();
    }

    private void loadRemoteKeys() {
        Roster roster = SparkManager.getRoster();
        for (RosterEntry entry : roster.getEntries()) {
            EntityFullJid userJid = SparkManager.getConnection().getUser();
            SessionID curSession = new SessionID(userJid.toString(), entry.getJid().toString(), "prpl-jabber");
            String remoteKey = _keyManager.getRemoteFingerprint(curSession);
            if (remoteKey != null) {
                boolean isVerified = _keyManager.isVerified(curSession);
                _keytable.addEntry(entry.getJid().toString(), remoteKey, isVerified);
            }
        }

        _keytable.addTableChangeListener(e -> {
            int col = e.getColumn();
            int row = e.getFirstRow();
            if (col != 2) {
                return;
            }
            boolean selection = (Boolean) _keytable.getValueAt(row, col);
            String JID = (String) _keytable.getValueAt(row, 0);
            EntityFullJid userJid = SparkManager.getConnection().getUser();
            SessionID curSelectedSession = new SessionID(userJid.toString(), JID, "prpl-jabber");
            if (!selection) {
                _keyManager.verify(curSelectedSession);
            } else {
                _keyManager.unverify(curSelectedSession);
            }
        });
    }

    private void buildGUI() {
        this.setBorder(BorderFactory.createTitledBorder(OTRResources.getString("otr.settings")));
        this.add(_enableOTR, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        this.add(_closeSessionOff, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 0), 0, 0));
        this.add(_closeSessionOnWindowClose, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        this.add(_currentKeyLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 5, 0, 0), 0, 0));
        this.add(_privateKey, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 0, 5), 0, 0));
        this.add(_renewPrivateKey, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0));
        this.add(_keytable, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(20, 5, 10, 5), 0, 0));
    }

    private String getCurrentLocalKey() {
        EntityFullJid userJid = SparkManager.getConnection().getUser();
        SessionID mySession = new SessionID(userJid.toString(), "no one", "prpl-jabber");
        String myKey = _keyManager.getLocalFingerprint(mySession);
        return myKey;
    }

    public JComponent getGUI() {
        _keytable = new OTRKeyTable();
        loadRemoteKeys();
        return this;
    }

    public boolean isOTREnabled() {
        return _enableOTR.isSelected();
    }

    public boolean isCloseOnDisc() {
        return _closeSessionOff.isSelected();
    }

    public boolean isCloseOnChatClose() {
        return _closeSessionOnWindowClose.isSelected();
    }

}
