/* This work has been placed into the public domain. */

package kiyut.alkitab.swing;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.AbstractListModel;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.crosswire.jsword.passage.Key;
import org.crosswire.jsword.passage.KeyFactory;
import org.crosswire.jsword.passage.NoSuchKeyException;
import org.crosswire.jsword.passage.Passage;
import org.crosswire.jsword.passage.PassageKeyFactory;
import org.crosswire.jsword.passage.RestrictionType;
import org.crosswire.jsword.passage.VerseRange;

/**
 * PassageChooser
 * 
 */
public class PassageChooser extends javax.swing.JPanel {
    protected ResourceBundle bundle = ResourceBundle.getBundle(this.getClass().getName());    
    
    protected KeyTree passageTree;
    protected PassageListModel passageListModel;
            
    protected KeyFactory keyFactory;
    protected Passage passage;
    
    protected boolean textAdjusting;
    
    /** Creates new PassageChooser */
    public PassageChooser() {
        initComponents();
        initCustom();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jToolBar1 = new javax.swing.JToolBar();
        addButton = new javax.swing.JButton();
        removeButton = new javax.swing.JButton();
        keyScrollPane = new javax.swing.JScrollPane();
        keyTree = new KeyTree();
        listScrollPane = new javax.swing.JScrollPane();
        passageList = new javax.swing.JList();
        jPanel2 = new javax.swing.JPanel();
        summaryLabel = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        passageTextArea = new javax.swing.JTextArea();

        setLayout(new java.awt.GridBagLayout());

        jPanel1.setLayout(new java.awt.GridBagLayout());

        jLabel2.setText(bundle.getString("CTL_AllVerses.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel1.add(jLabel2, gridBagConstraints);

        jLabel3.setText(bundle.getString("CTL_SelectedVerses.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel1.add(jLabel3, gridBagConstraints);

        jToolBar1.setFloatable(false);
        jToolBar1.setOrientation(1);
        jToolBar1.setRollover(true);

        addButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/right.png"))); // NOI18N
        addButton.setToolTipText(bundle.getString("HINT_AddVerses.Text")); // NOI18N
        addButton.setFocusPainted(false);
        addButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
        jToolBar1.add(addButton);

        removeButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/left.png"))); // NOI18N
        removeButton.setToolTipText(bundle.getString("HINT_RemoveVerses.Text")); // NOI18N
        removeButton.setFocusPainted(false);
        removeButton.setMargin(new java.awt.Insets(1, 1, 1, 1));
        jToolBar1.add(removeButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(6, 8, 6, 8);
        jPanel1.add(jToolBar1, gridBagConstraints);

        keyScrollPane.setPreferredSize(new java.awt.Dimension(230, 430));
        keyScrollPane.setViewportView(keyTree);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.4;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel1.add(keyScrollPane, gridBagConstraints);

        listScrollPane.setPreferredSize(new java.awt.Dimension(230, 100));
        listScrollPane.setViewportView(passageList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.4;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel1.add(listScrollPane, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 0.8;
        add(jPanel1, gridBagConstraints);

        jPanel2.setLayout(new java.awt.GridBagLayout());

        summaryLabel.setText(bundle.getString("CTL_Summary.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel2.add(summaryLabel, gridBagConstraints);

        passageTextArea.setLineWrap(true);
        passageTextArea.setRows(5);
        passageTextArea.setWrapStyleWord(true);
        jScrollPane1.setViewportView(passageTextArea);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel2.add(jScrollPane1, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weighty = 0.2;
        gridBagConstraints.insets = new java.awt.Insets(8, 0, 0, 0);
        add(jPanel2, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addButton;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JScrollPane keyScrollPane;
    private javax.swing.JTree keyTree;
    private javax.swing.JScrollPane listScrollPane;
    private javax.swing.JList passageList;
    private javax.swing.JTextArea passageTextArea;
    private javax.swing.JButton removeButton;
    private javax.swing.JLabel summaryLabel;
    // End of variables declaration//GEN-END:variables
    
    protected void initCustom() {
        textAdjusting = false;
        passageTree = (KeyTree)keyTree;
        passageTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        passageTree.setModel(new BibleKeyTreeModel(BibleKeyTreeModel.LEVEL_VERSE));
        
        passageListModel = new PassageListModel();
        passageList.setModel(passageListModel);
        
        keyFactory = PassageKeyFactory.instance();
        passage = (Passage)keyFactory.createEmptyKeyList();
        
        summaryLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
        
        /*
         Disable this, UI Gesture does not match, because double click is tree expand
         passageTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent evt) {
                if (evt.getClickCount() != 2) { return; }
                addPassage();
            }
        });*/
        
        passageList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent evt) {
                if (evt.getClickCount() != 2) { return; }
                removePassage();
            }
        });
        
        passageTextArea.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e) {
                textUpdated();
            }

            public void removeUpdate(DocumentEvent e) {
                textUpdated();
            }

            public void changedUpdate(DocumentEvent e) {
                textUpdated();
            }
            
            private void textUpdated() {
                if (textAdjusting) { return; }
                textAdjusting = true;
                updatePassage();
                textAdjusting = false;
            }
        });
        
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addPassage();
            }
        });
        
        removeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removePassage();
            }
        });
    }
    
    /** 
     * @param keyString Passage Key as String or null
     */
    public void setPassage(String keyString) {
        if (keyString != null) {
            passageTextArea.setText(keyString);
        }
    }
    
    /** Show as Dialog 
     * @param parentComponent {@code Component}
     */
    public int showDialog(Component parentComponent) {
        int choice = JOptionPane.showConfirmDialog(parentComponent,this,bundle.getString("CTL_Title.Text"),JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
        return choice;
    }
    
    public Key getKey() {
        return this.passage;
    }
    
    protected void updatePassage() {
        String invalidMsg = null;
        try {
            if (textAdjusting) {
                Passage tPassage = (Passage) keyFactory.getKey(passageTextArea.getText());
                passage.clear();
                passage.addAll(tPassage);
            } else {
                passageTextArea.setText(passage.getName());
            }
            passageListModel.setPassage(passage);
        } catch (NoSuchKeyException ex) {
            invalidMsg = ex.getMessage();
        } 
        
        String msg = bundle.getString("CTL_Summary.Text");
        if (invalidMsg == null) {
            if (passage.countVerses() > 0) {
                msg = msg + ": " + passage.getOverview();
            }
            summaryLabel.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
        } else {
            msg = msg + ": " + invalidMsg;
            summaryLabel.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
        }
        
        summaryLabel.setText(msg);
    }
    
    protected void addPassage() {
        TreePath[] selection = passageTree.getSelectionPaths();
        if (selection == null) { return; }
            
        for (int i = 0; i < selection.length; i++) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)selection[i].getLastPathComponent();
            VerseRange verseRange = (VerseRange)node.getUserObject();
            passage.add(verseRange);
        }
        updatePassage();
    }
    
    protected void removePassage() {
        Object[] selection = passageList.getSelectedValues();
        if (selection == null) { return; }
        
        for (int i = 0; i < selection.length; i++) {
            VerseRange verseRange = (VerseRange)selection[i];
            passage.remove(verseRange);
        }
        updatePassage();
    }
    
    public class PassageListModel extends AbstractListModel {
        protected Passage passage;
        protected List data;
        
        public PassageListModel() {
            data = new ArrayList();
        }
        
        public void setPassage(Passage passage) {
            fireIntervalRemoved(this, 0, getSize());
            
            this.passage = passage;
            data.clear();
            
            if (passage == null) {
                return;
            }
            
            passage.optimizeReads();
            
            Iterator iter = passage.rangeIterator(RestrictionType.CHAPTER);
            while (iter.hasNext()) {
                data.add(iter.next());
            }
            
            fireIntervalAdded(this, 0, getSize());
        }
        
        public Passage getPassage() {
            return this.passage;
        }
        
        public int getSize() {
            return data.size();
        }

        public Object getElementAt(int index) {
            return data.get(index);
        }
        
    }
}
