/**
 * *************************************************************************
 * Copyright (C) 2009 by Paul Lutus * lutusp@arachnoid.com * * This program is
 * free software; you can redistribute it and/or modify * it under the terms of
 * the GNU General Public License as published by * the Free Software
 * Foundation; either version 2 of the License, or * (at your option) any later
 * version. * * This program is distributed in the hope that it will be useful,
 * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General
 * Public License for more details. * * You should have received a copy of the
 * GNU General Public License * along with this program; if not, write to the *
 * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA. *
 * *************************************************************************
 */
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MyHelpPane.java
 *
 * Created on Feb 18, 2009, 2:12:32 PM
 */
package tankcalc;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.text.Highlighter.Highlight;
import javax.swing.text.html.*;

/**
 *
 * @author lutusp
 */
final public class HelpPane extends javax.swing.JPanel {

    TankCalc parent;
    Stack<HelpState> undoStack;
    Stack<HelpState> redoStack;
    Document doc;
    String oldSearch = "";
    int oldPos = 0;
    Object oldHighlight = null;
    Highlighter highlighter = null;
    Highlighter.HighlightPainter highlightPainter = null;

    /**
     * Creates new form MyHelpPane
     */
    public HelpPane(TankCalc p) {
        parent = p;
        initComponents();
        helpTextPane.setContentType("text/html;charset=UTF-8");
        doc = helpTextPane.getDocument();
        undoStack = new Stack<>();
        redoStack = new Stack<>();
        highlighter = helpTextPane.getHighlighter();
        highlightPainter = new DefaultHighlighter.DefaultHighlightPainter(new Color(200, 255, 200));
        setupHelp();
        setButtons();
    }

    // help resource related
    void setupHelp() {
        String fn = "help_resources/helpText.html";
        try {
            InputStream is = parent.getClass().getResourceAsStream(fn);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
            is.close();
            String s = sb.toString();
            s = s.replaceAll("#version#", parent.VERSION);
            URL url = parent.getClass().getResource(fn).toURI().toURL();
            helpTextPane.setText(s);
            helpTextPane.select(0, 0);
            ((HTMLDocument) helpTextPane.getDocument()).setBase(url);
        } catch (Exception e) {
            System.out.println("setupHelp: " + e);
            e.printStackTrace(System.out);
        }
    }

    public int getScrollPos() {
        return helpScrollPane.getVerticalScrollBar().getValue();
    }

    public void setScrollPos(int v) {
        helpScrollPane.getVerticalScrollBar().setValue(v);
    }

    // manageHyperlinks tries to find and launch a browser
    private void manageHyperlinks(HyperlinkEvent evt) {
        URL url = evt.getURL();
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
            String surl = evt.getURL().toString();
            if (surl.matches("http://.*")) {
                //if (parent.applet) {
                //    parent.setStatus("Sorry, applets can't follow hyperlinks.", true);
                //} else {
                try {
                    java.awt.Desktop.getDesktop().browse(java.net.URI.create(surl));
                } catch (Exception e) {
                    System.out.println(e);
                }
                //}
            } else { // possibly a bookmark
                if (surl.matches(".*#.*")) {
                    try {
                        undoPush();
                        helpTextPane.scrollToReference(url.getRef());

                    } catch (Exception e) {
                        System.out.println(e);
                    }
                }
            }
        }
    }

    void undoPop() {
        if (undoStack.size() > 0) {
            redoPush();
            removeOldHighlight();
            HelpState hs = undoStack.pop();
            helpScrollPane.getVerticalScrollBar().setValue(hs.scrollBar);
            try {
                oldHighlight = highlighter.addHighlight(hs.selectStart,
                        hs.selectEnd, highlightPainter);
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            setButtons();

        } else {
            parent.beep();
        }

    }

    void redoPop() {
        if (redoStack.size() > 0) {
            undoPush();
            removeOldHighlight();
            HelpState hs = redoStack.pop();
            helpScrollPane.getVerticalScrollBar().setValue(hs.scrollBar);
            try {
                oldHighlight = highlighter.addHighlight(hs.selectStart,
                        hs.selectEnd, highlightPainter);
            } catch (BadLocationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            setButtons();

        } else {
            parent.beep();
        }

    }

    void undoPush() {
        int ss = 0;
        int se = 0;
        Highlight[] ha = highlighter.getHighlights();
        if (ha.length > 0) {
            ss = ha[0].getStartOffset();
            se = ha[0].getEndOffset();
        }
        int sbp = helpScrollPane.getVerticalScrollBar().getValue();
        undoStack.push(new HelpState(sbp, ss, se));
        setButtons();

    }

    void redoPush() {
        int ss = 0;
        int se = 0;
        Highlight[] ha = highlighter.getHighlights();
        if (ha.length > 0) {
            ss = ha[0].getStartOffset();
            se = ha[0].getEndOffset();
        }
        int sbp = helpScrollPane.getVerticalScrollBar().getValue();
        redoStack.push(new HelpState(sbp, ss, se));
        setButtons();

    }

    void setButtons() {
        undoButton.setEnabled(undoStack.size() > 0);
        redoButton.setEnabled(redoStack.size() > 0);
    }

    void removeOldHighlight() {
        if (oldHighlight != null) {
            highlighter.removeHighlight(oldHighlight);
            oldHighlight
                    = null;
        }

    }

    void manageHelpTextField(KeyEvent evt) {
        //String code = KeyEvent.getKey_Text(evt.getKeyCode());
        // if a function key, go to main command switchboard
        //if (code.matches("F\\d")) {
        //parent.handleKeyPressed(evt);
        //} else {
        try {

            removeOldHighlight();
            doc
                    = helpTextPane.getDocument();
            int len = doc.getLength();
            String content = doc.getText(0, len).toLowerCase();
            String search = findTextField.getText().toLowerCase();
            if (!search.equals(oldSearch)) {
                oldPos = 0;
            }

            oldSearch = search;
            int p = content.indexOf(search, oldPos);
            if (p == -1) {
                oldPos = 0;
                p
                        = content.indexOf(search, oldPos);
            }

            if (p >= 0) { // if found
                
                int slen = search.length();
                Rectangle r = helpTextPane.modelToView(p);
                // aim for the middle of the screen
                int pos = r.y - helpScrollPane.getHeight() / 2;
                // but don't try for the impossible
                pos
                        = (pos < 0) ? 0 : pos;
                helpScrollPane.getVerticalScrollBar().setValue(pos);
                // now highlight the found text in our nonfocused text pane
                oldHighlight
                        = highlighter.addHighlight(p, p + slen, highlightPainter);
                oldPos
                        = p + 1; // to find next case
                undoPush();
            } else {
                parent.beep();
            }

        } catch (Exception e) {
            System.out.println(e);
        }
//}

    }

    /**
     * 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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPanel1 = new javax.swing.JPanel();
        undoButton = new javax.swing.JButton();
        redoButton = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        findTextField = new javax.swing.JTextField();
        helpScrollPane = new javax.swing.JScrollPane();
        helpTextPane = new javax.swing.JTextPane();

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

        undoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/go-previous.png"))); // NOI18N
        undoButton.setToolTipText("Go back");
        undoButton.setFocusable(false);
        undoButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                undoButtonActionPerformed(evt);
            }
        });
        jPanel1.add(undoButton);

        redoButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/tankcalc/icons/go-next.png"))); // NOI18N
        redoButton.setToolTipText("Go forward");
        redoButton.setFocusable(false);
        redoButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                redoButtonActionPerformed(evt);
            }
        });
        jPanel1.add(redoButton);

        jLabel1.setText("Search:");
        jPanel1.add(jLabel1);

        findTextField.setToolTipText("<html>Quick search: type a search string,<br/>press Enter to find the next case</html>");
        findTextField.setFocusCycleRoot(true);
        findTextField.setMinimumSize(new java.awt.Dimension(150, 27));
        findTextField.setPreferredSize(new java.awt.Dimension(150, 27));
        findTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                findTextFieldKeyReleased(evt);
            }
        });
        jPanel1.add(findTextField);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        add(jPanel1, gridBagConstraints);

        helpScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));

        helpTextPane.setEditable(false);
        helpTextPane.setFocusable(false);
        helpTextPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
            public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
                helpTextPaneHyperlinkUpdate(evt);
            }
        });
        helpScrollPane.setViewportView(helpTextPane);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        add(helpScrollPane, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

    private void helpTextPaneHyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {//GEN-FIRST:event_helpTextPaneHyperlinkUpdate
        // TODO add your handling code here:
        manageHyperlinks(evt);
    }//GEN-LAST:event_helpTextPaneHyperlinkUpdate

    private void findTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_findTextFieldKeyReleased
        // TODO add your handling code here:
        manageHelpTextField(evt);
}//GEN-LAST:event_findTextFieldKeyReleased

    private void redoButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_redoButtonActionPerformed
        // TODO add your handling code here:
        redoPop();
    }//GEN-LAST:event_redoButtonActionPerformed

    private void undoButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_undoButtonActionPerformed
        // TODO add your handling code here:
        undoPop();
    }//GEN-LAST:event_undoButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    protected javax.swing.JTextField findTextField;
    private javax.swing.JScrollPane helpScrollPane;
    private javax.swing.JTextPane helpTextPane;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton redoButton;
    private javax.swing.JButton undoButton;
    // End of variables declaration//GEN-END:variables
}
