package kiyut.alkitab.swing;

import kiyut.alkitab.api.BookViewer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.event.HyperlinkListener;
import kiyut.alkitab.api.SwordURI;
import kiyut.alkitab.api.event.BookChangeEvent;
import kiyut.swing.combo.SeparatorComboBox;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookFilters;
import org.crosswire.jsword.book.Books;
import org.crosswire.jsword.index.search.DefaultSearchModifier;
import org.crosswire.jsword.index.search.DefaultSearchRequest;
import org.crosswire.jsword.passage.Key;
import org.crosswire.jsword.passage.Key;
import org.crosswire.jsword.passage.PassageTally;
import org.crosswire.jsword.passage.RestrictionType;

/**
 * Parallel Book 
 * 
 */
public class ParallelBookViewerPane extends AbstractBookViewerPane {
    
    protected ResourceBundle bundle = ResourceBundle.getBundle(this.getClass().getName());    
    
    protected ParallelBookTextPane bookTextPane;
    
    protected ActionListener bookComboActionListener;
    
    /** Creates new ParallelBookViewerPane */
    public ParallelBookViewerPane() {
        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;

        splitPane = new javax.swing.JSplitPane();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jToolBar1 = new javax.swing.JToolBar();
        addBookButton = new javax.swing.JButton();
        removeBookButton = new javax.swing.JButton();
        compareCheckBox = new javax.swing.JCheckBox();
        booksComboPane = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        passageTextArea = new javax.swing.JTextArea();
        jToolBar2 = new javax.swing.JToolBar();
        passageChooserButton = new javax.swing.JButton();
        passageGoButton = new javax.swing.JButton();
        jPanel4 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        searchTextArea = new javax.swing.JTextArea();
        jToolBar3 = new javax.swing.JToolBar();
        advancedSearchButton = new javax.swing.JButton();
        searchGoButton = new javax.swing.JButton();
        bookScrollPane = new javax.swing.JScrollPane();

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

        splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(6, 6, 6, 6));
        jPanel1.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText(bundle.getString("CTL_Book.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 6);
        jPanel1.add(jLabel1, gridBagConstraints);

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

        addBookButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/plus.png"))); // NOI18N
        addBookButton.setToolTipText(bundle.getString("CTL_AddBook.Text")); // NOI18N
        addBookButton.setFocusable(false);
        addBookButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        addBookButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(addBookButton);

        removeBookButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/minus.png"))); // NOI18N
        removeBookButton.setToolTipText(bundle.getString("CTL_RemoveBook.Text")); // NOI18N
        removeBookButton.setFocusable(false);
        removeBookButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        removeBookButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(removeBookButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanel1.add(jToolBar1, gridBagConstraints);

        compareCheckBox.setText(bundle.getString("CTL_Compare.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 3);
        jPanel1.add(compareCheckBox, gridBagConstraints);

        booksComboPane.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 5, 0));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
        jPanel1.add(booksComboPane, gridBagConstraints);

        jLabel2.setText(bundle.getString("CTL_Search.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(7, 0, 0, 6);
        jPanel1.add(jLabel2, gridBagConstraints);

        jLabel3.setText(bundle.getString("CTL_Passsage.Text")); // NOI18N
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(7, 0, 0, 6);
        jPanel1.add(jLabel3, gridBagConstraints);

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

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

        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 = 1.0;
        jPanel2.add(jScrollPane1, gridBagConstraints);

        jToolBar2.setFloatable(false);
        jToolBar2.setRollover(true);

        passageChooserButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/edit.png"))); // NOI18N
        passageChooserButton.setToolTipText(bundle.getString("CTL_PassageChooser.Text")); // NOI18N
        passageChooserButton.setFocusable(false);
        passageChooserButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        passageChooserButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar2.add(passageChooserButton);

        passageGoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/refresh.png"))); // NOI18N
        passageGoButton.setToolTipText(bundle.getString("CTL_PassageGo.Text")); // NOI18N
        passageGoButton.setFocusable(false);
        passageGoButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        passageGoButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar2.add(passageGoButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 0, 3);
        jPanel2.add(jToolBar2, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 3;
        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);
        jPanel1.add(jPanel2, gridBagConstraints);

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

        searchTextArea.setLineWrap(true);
        searchTextArea.setWrapStyleWord(true);
        jScrollPane2.setViewportView(searchTextArea);

        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 = 1.0;
        jPanel4.add(jScrollPane2, gridBagConstraints);

        jToolBar3.setFloatable(false);
        jToolBar3.setRollover(true);

        advancedSearchButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/edit.png"))); // NOI18N
        advancedSearchButton.setToolTipText(bundle.getString("CTL_AdvancedSearch.Text")); // NOI18N
        advancedSearchButton.setFocusable(false);
        advancedSearchButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        advancedSearchButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar3.add(advancedSearchButton);

        searchGoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/kiyut/alkitab/swing/refresh.png"))); // NOI18N
        searchGoButton.setToolTipText(bundle.getString("CTL_PassageGo.Text")); // NOI18N
        searchGoButton.setFocusable(false);
        searchGoButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        searchGoButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar3.add(searchGoButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(1, 3, 0, 3);
        jPanel4.add(jToolBar3, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
        jPanel1.add(jPanel4, gridBagConstraints);

        splitPane.setLeftComponent(jPanel1);
        splitPane.setRightComponent(bookScrollPane);

        add(splitPane, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addBookButton;
    private javax.swing.JButton advancedSearchButton;
    private javax.swing.JScrollPane bookScrollPane;
    private javax.swing.JPanel booksComboPane;
    private javax.swing.JCheckBox compareCheckBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JToolBar jToolBar2;
    private javax.swing.JToolBar jToolBar3;
    private javax.swing.JButton passageChooserButton;
    private javax.swing.JButton passageGoButton;
    private javax.swing.JTextArea passageTextArea;
    private javax.swing.JButton removeBookButton;
    private javax.swing.JButton searchGoButton;
    private javax.swing.JTextArea searchTextArea;
    private javax.swing.JSplitPane splitPane;
    // End of variables declaration//GEN-END:variables
 
    protected void initCustom() {
        maximumBook = 5;
        
        splitPane.setOneTouchExpandable(true);
        
        bookTextPane = new ParallelBookTextPane();
        bookScrollPane.setViewportView(bookTextPane);
        
        getActionMap().setParent(bookTextPane.getActionMap());
        
        addBookButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                addBook(null);
            }
        });
        
        removeBookButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                removeBook(booksComboPane.getComponentCount()-1);
            }
        });
        
        bookComboActionListener = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                JComboBox comboBox = (JComboBox) evt.getSource();
                int index = -1;
                for (int i = 0; i < booksComboPane.getComponentCount(); i++) {
                    if (comboBox.equals(booksComboPane.getComponent(i))) {
                        index = i;
                        break;
                    }
                }
                if (index == -1) {
                    return;
                }

                String bookName = comboBox.getSelectedItem().toString();
                setBook(index, bookName);
            }
        };
        
        compareCheckBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                bookTextPane.setCompareView(compareCheckBox.isSelected());
                bookTextPane.refresh(true);
            }
        });
        
        passageChooserButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                PassageChooser passageChooser = new PassageChooser();
                passageChooser.setPassage(passageTextArea.getText());
                int choice = passageChooser.showDialog(ParallelBookViewerPane.this);
                if (choice != JOptionPane.OK_OPTION) {
                    return;
                }
                Key key = passageChooser.getKey();
                setKey(key);
                refresh();
            }
        });
        
        passageGoButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                String str = passageTextArea.getText();
                setKey(str);
                refresh();
            }
        });
        
        advancedSearchButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                SearchPane searchPane = new SearchPane();
                int choice = searchPane.showDialog(ParallelBookViewerPane.this);
                if (choice != JOptionPane.OK_OPTION) {
                    return;
                }
                searchTextArea.setText(searchPane.getSearchString());
                //Key key = passageChooser.getKey();
                //setPassage(key);
                //refresh();
            }
        });
        
        searchGoButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                search(searchTextArea.getText());
            }
        });
        
        passageTextArea.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent evt) {
                if (evt.getKeyCode() != KeyEvent.VK_ENTER) {
                    return;
                }
                
                evt.consume();
                setKey(passageTextArea.getText());
                refresh();
            }
        });
        
        searchTextArea.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent evt) {
                if (evt.getKeyCode() != KeyEvent.VK_ENTER) {
                    return;
                }
                
                evt.consume();
                search(searchTextArea.getText());
                refresh();
            }
        });
        
        // default try to display something
        String str = "Genesis 1";
        passageTextArea.setText(str);
    }
    
    @Override
    public String getName() {
        if (bookTextPane == null) {
            return "";
        }
        
        List<Book> books = bookTextPane.getBooks();
        
        if (books.isEmpty()) {
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        
        for (int i=0;i <books.size(); i++) {
            if (i > 0) {
                sb.append("=");
            } 
            sb.append(books.get(i).getInitials());
        }
        
        return sb.toString();
    }
    
    public void addHyperlinkListener(HyperlinkListener listener) {
        bookTextPane.addHyperlinkListener(listener);
    }
    
    public void removeHyperlinkListener(HyperlinkListener listener) {
        bookTextPane.removeHyperlinkListener(listener);
    }
    
    public void openURI(SwordURI uri) {
        if (!uri.getFragment().equals("")) {
            passageTextArea.setText(uri.getFragment());
            setKey(passageTextArea.getText());
        } 
        
        if (uri.getPath().equals("")) {
            if (bookTextPane.getBooks().isEmpty()) {
                addBookButton.doClick();
                
            } else {
                refresh();
            }
        } else {
            Book book =  Books.installed().getBook(uri.getPath());
            if (book == null) { return; }
            addBook(book.getInitials());
        }
    }
    
    /** Add Book
     * @param bookName Book Initials or Book Name
     */
    protected void addBook(String bookName) {
        int count = booksComboPane.getComponentCount();
        if (count >= maximumBook) {
            return;
        }
        JComboBox comboBox = createBookComboBox();
        comboBox.addActionListener(bookComboActionListener);
        booksComboPane.add(comboBox);
        booksComboPane.revalidate();
        booksComboPane.repaint();

        if (bookName == null) {
            bookName = comboBox.getItemAt(0).toString();
        }
        
        Book book = Books.installed().getBook(bookName);
        if (book == null) {
            return;
        }
        bookTextPane.getBooks().add(book);

        firePropertyChange(BookViewer.VIEWER_NAME, null, getName());
        
        if (count == 0) {
            setKey(passageTextArea.getText());
        }
        
        comboBox.setSelectedItem(bookName);
    }
    
    /** Remove book at particular index
     * @param index index at which the specified book is to be removed.
     */
    protected void removeBook(int index) {
        if (index >= booksComboPane.getComponentCount()) {
            return;
        }
        
        if (booksComboPane.getComponentCount() == 1) {
            return;
        }
        
        
        //comboBox.addActionListener(bookComboActionListener);
        JComboBox comboBox = (JComboBox) booksComboPane.getComponent(index);
        booksComboPane.remove(index);
        booksComboPane.revalidate();
        booksComboPane.repaint();
        comboBox.removeActionListener(bookComboActionListener);

        bookTextPane.getBooks().remove(index);
        firePropertyChange(BookViewer.VIEWER_NAME, null, getName());
        fireBookChange(new BookChangeEvent(this));

        bookTextPane.refresh(true);
    }
    
    /** Replaces book at particular index
     * @param index index at which the specified book is to be replaced.
     * @param bookName Book Initials or Book Name
     */
    protected void setBook(int index, String bookName) {
        Book book = Books.installed().getBook(bookName);
        if (book == null) {
            return;
        }

        bookTextPane.getBooks().set(index, book);

        firePropertyChange(BookViewer.VIEWER_NAME, null, getName());
        fireBookChange(new BookChangeEvent(this));

        refresh();
    }
    
    public List<Book> getBooks() {
        List<Book> srcBooks = bookTextPane.getBooks();
        return Collections.unmodifiableList(srcBooks);
    }

    public int getBookCount() {
        return bookTextPane.getBooks().size();
    }

    
    public void compareView(boolean compare) {
        bookTextPane.setCompareView(compare);
    }

    /** Return {@code true} or {@code false}
     * @return {@code true} or {@code false}
     */
    @Override
    public boolean isCompareView() {
        return bookTextPane.isCompareView();
    }
    
    protected void setKey(String keyString) {
        Key key = null;
        List<Book> books = bookTextPane.getBooks();
        if (!books.isEmpty()) {
            key = books.get(0).getValidKey(keyString);
            setKey(key);
        } 
    }
    
    public void setKey(Key key) {
        passageTextArea.setText(key.toString());
        passageTextArea.setCaretPosition(0);
        bookTextPane.setKey(key);
    }
    
    public Key getKey() {
        /*Key key = null;
        List<Book> books = bookTextPane.getBooks();
        if (!books.isEmpty()) {
            key = books.get(0).getValidKey(passageString);
        } 
        return key;
         */
        return bookTextPane.getKey();
    }

    public void refresh() {
        bookTextPane.refresh(true);
    }
    
    protected void search(String searchString) {
        if (searchString == null || searchString.length() == 0) {
            return;
        }
        
        List<Book> books = bookTextPane.getBooks();
        if (books.isEmpty()) { 
            JOptionPane.showMessageDialog(this, bundle.getString("MSG_EmptyBooks.Text"), bundle.getString("MSG_EmptyBooks.Title"), JOptionPane.WARNING_MESSAGE);
            return; 
        }

        boolean rank = true;

        DefaultSearchModifier modifier = new DefaultSearchModifier();
        modifier.setRanked(rank);
        
        Key results = null;
        int total = 0;
        
        try {
            results =  books.get(0).find(new DefaultSearchRequest(searchString, modifier));
        } catch (Exception ex) {
            Logger logger = Logger.getLogger(this.getClass().getName());
            logger.log(Level.WARNING, ex.getMessage(), ex);
            return;
        }
        
        total = results.getCardinality();
        int partial = total;
        
        if (total == 0) {
            Object[] args = {searchString};
            String msg = MessageFormat.format(bundle.getString("MSG_SearchNoHits.Text"), args);
            JOptionPane.showMessageDialog(this, msg , bundle.getString("MSG_SearchHits.Title"), JOptionPane.WARNING_MESSAGE);
            return;
        }

        if (results instanceof PassageTally || rank)  {
            PassageTally tally = (PassageTally) results;
            tally.setOrdering(PassageTally.ORDER_TALLY);
            
            // TODO replace this with value from Preferences
            //int rankCount = getNumRankedVerses();
            int rankCount = 200;
            if (rankCount > 0 && rankCount < total)  {
                tally.trimRanges(rankCount, RestrictionType.NONE);
                partial = rankCount;
            }
        }

        if (total == partial) {
            Object[] args = {searchString,new Integer(total)};
            String msg = MessageFormat.format(bundle.getString("MSG_SearchHits.Text"), args);
            JOptionPane.showMessageDialog(this, msg , bundle.getString("MSG_SearchHits.Title"), JOptionPane.WARNING_MESSAGE);
        } else {
            Object[] args = {searchString,new Integer(partial),new Integer(total)};
            String msg = MessageFormat.format(bundle.getString("MSG_SearchPartialHits.Text"), args);
            JOptionPane.showMessageDialog(this, msg , bundle.getString("MSG_SearchHits.Title"), JOptionPane.WARNING_MESSAGE);
        }
        
        setKey(results);
        refresh();
    }
    
    /** Return JComboBox with book initials sorted by Bible and Commentary 
     * @return JComboBox
     */
    protected JComboBox createBookComboBox() {
        List<Book> books = new ArrayList<Book>();
        List<String> bookInitials = new ArrayList<String>();
        Comparator<Book> comparator = createBookInitialsComparator();
        
        // bible
        List tBooks = Books.installed().getBooks(BookFilters.getOnlyBibles());
        books.addAll(tBooks);
        Collections.sort(books, comparator);
        for (int i=0; i<books.size(); i++) {
            bookInitials.add(books.get(i).getInitials());
        }
        
        // Commentary
        books.clear();
        tBooks = Books.installed().getBooks(BookFilters.getCommentaries());
        books.addAll(tBooks);
        Collections.sort(books, comparator);
        if (books.size() > 0) {
            bookInitials.add(SeparatorComboBox.DEFAULT_SEPARATOR);
        }
        for (int i=0; i<books.size(); i++) {
            bookInitials.add(books.get(i).getInitials());
        }
        
        SeparatorComboBox comboBox = new SeparatorComboBox(bookInitials.toArray());
        comboBox.setPrototypeDisplayValue("BOOKINITIALS");
        return comboBox;
    }
    
    /** XXX just an implementation of genericfied book initial comparator, remove when JSword support generic */
    protected Comparator<Book> createBookInitialsComparator() {
        Comparator<Book> comp = new Comparator<Book>() {
            public int compare(Book o1, Book o2) {
                return o1.getInitials().compareTo(o2.getInitials());
            }
            
        };
        
        return comp;
    }
}
