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

package kiyut.alkitab.bookviewer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import kiyut.alkitab.api.ViewerHints;
import kiyut.swing.dialog.DialogESC;
import kiyut.swing.text.xml.XMLContext;
import kiyut.swing.text.xml.XMLEditorKit;
import org.crosswire.common.xml.Converter;
import org.crosswire.common.xml.FormatType;
import org.crosswire.common.xml.PrettySerializingContentHandler;
import org.crosswire.common.xml.SAXEventProvider;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookData;
import org.crosswire.jsword.book.BookMetaData;
import org.crosswire.jsword.passage.Key;
import org.crosswire.jsword.passage.Verse;
import org.xml.sax.ContentHandler;

/**
 * Display the OSIS and HTML source for the the book
 * 
 */
public class SourceViewerPane extends javax.swing.JPanel {
    
    protected ResourceBundle bundle = ResourceBundle.getBundle(this.getClass().getName());
    protected BookTextPane bookTextPane;
    
    /** Creates new SourceViewerPane */
    public SourceViewerPane() {
        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() {

        jTabbedPane1 = new javax.swing.JTabbedPane();
        rawScrollPane = new javax.swing.JScrollPane();
        rawEditorPane = new ExtendedEditorPane();
        osisScrollPane = new javax.swing.JScrollPane();
        osisEditorPane = new ExtendedEditorPane();
        htmlScrollPane = new javax.swing.JScrollPane();
        htmlEditorPane = new ExtendedEditorPane();

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

        rawScrollPane.setViewportView(rawEditorPane);

        jTabbedPane1.addTab(bundle.getString("CTL_Raw.Text"), rawScrollPane); // NOI18N

        osisScrollPane.setViewportView(osisEditorPane);

        jTabbedPane1.addTab(bundle.getString("CTL_OSIS.Text"), osisScrollPane); // NOI18N

        htmlScrollPane.setViewportView(htmlEditorPane);

        jTabbedPane1.addTab(bundle.getString("CTL_HTML.Text"), htmlScrollPane); // NOI18N

        add(jTabbedPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JEditorPane htmlEditorPane;
    private javax.swing.JScrollPane htmlScrollPane;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JEditorPane osisEditorPane;
    private javax.swing.JScrollPane osisScrollPane;
    private javax.swing.JEditorPane rawEditorPane;
    private javax.swing.JScrollPane rawScrollPane;
    // End of variables declaration//GEN-END:variables
    
    protected void initCustom() {
        Dimension size = new Dimension(780,540);
        this.setPreferredSize(size);

        Color background = UIManager.getColor("TextPane.background");

        int fontSize = 10;
        try {
            int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
            fontSize = (int)Math.round((double)fontSize * dpi / 72.0);
            
            /*Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
            if (size.width >= 1280 || size.height >= 1024) {
                fontSize = 13;
            }*/
        } catch (Exception ex) {
            Logger logger = Logger.getLogger(this.getClass().getName());
            logger.log(Level.CONFIG,ex.getMessage(),ex);
        }

        Font font = new Font("Monospaced", Font.PLAIN, fontSize);

        rawEditorPane.setEditable(false);
        rawEditorPane.setBackground(background);

        XMLContext ctx = new XMLContext(font);
        XMLEditorKit kit = new XMLEditorKit(ctx);
        osisEditorPane.setEditorKitForContentType(XMLEditorKit.XML_MIME_TYPE, kit);
        osisEditorPane.setContentType(XMLEditorKit.XML_MIME_TYPE);
        osisEditorPane.setEditable(false);
        osisEditorPane.setBackground(background);

        ctx = new XMLContext(font);
        kit = new XMLEditorKit(ctx);
        htmlEditorPane.setEditorKitForContentType(XMLEditorKit.XML_MIME_TYPE, kit);
        htmlEditorPane.setContentType(XMLEditorKit.XML_MIME_TYPE);
        htmlEditorPane.setEditable(false);
        htmlEditorPane.setBackground(background);
    }
    
    /** Show as Dialog 
     * @param owner {@code Component}
     */
    public void showDialog(Component owner, boolean modal) {
        JDialog dialog = null;
        
        if (owner != null) {
            Component comp = owner;
            if (!(comp instanceof Frame || comp instanceof Dialog)) {
                comp = SwingUtilities.getWindowAncestor(owner);
            }
            if (comp instanceof Frame) {
                dialog = new DialogESC((Frame)comp, bundle.getString("CTL_Title.Text"), true);
            } else if (comp instanceof Dialog) {
                dialog = new DialogESC((Dialog)comp, bundle.getString("CTL_Title.Text"), true);
            } 
        }
        
        dialog.setLayout(new BorderLayout());
        dialog.add(this,BorderLayout.CENTER);
        dialog.pack();
        if (owner != null) {
            dialog.setLocationRelativeTo(owner);
        }
        
        dialog.setVisible(true);
    }

    public void initSource(BookTextPane bookTextPane) {
        this.bookTextPane = bookTextPane;
        try {
            initSourceImpl(bookTextPane.getBooks(), bookTextPane.getKey(), bookTextPane.isCompareView());
        } catch (Exception ex) {
            Logger logger = Logger.getLogger(this.getClass().getName());
            logger.log(Level.WARNING, ex.getMessage(), ex);
        }
    }

    /** Init this component with the source text
     * @Deprecated replaced with #initSource(BookTextPane)
     */
    @SuppressWarnings("unchecked")
    private void initSourceImpl(List<Book> books, Key key, boolean compareView) throws Exception {
        if (books.isEmpty() || key == null) {
            return;
        }

        BookData bookData = new BookData(books.toArray(new Book[books.size()]), key, compareView);
        BookMetaData bmd = bookData.getFirstBook().getBookMetaData();
        if (bmd == null) {
            return;
        }

        //boolean ltr = bmd.isLeftToRight();

        /////////////
        // Raw Text
        
        StringBuilder rawText = new StringBuilder();
        Iterator<Key> iter = key.iterator();
        while (iter.hasNext()) {
            Key curKey = iter.next();

            // XXX JSword Bug? Non bible key getOsisID end up in endless loop
            String osisID = null;
            if (curKey instanceof Verse) {
                osisID = curKey.getOsisID();
            }
            //System.out.println("BookTextPane.refreshImpl osisID: " + osisID);
            for (int i = 0; i < books.size(); i++) {
                Book book = books.get(i);
                if (rawText.length() > 0) {
                    rawText.append(System.getProperty("line.separator"));
                }
                rawText.append(book.getInitials());
                if (osisID != null) {
                    rawText.append(':').append(osisID);
                }
                rawText.append(" - ").append(book.getRawText(curKey));
            }
        }

        ///////////////
        // OSIS Text

        SAXEventProvider osissep = bookData.getSAXEventProvider();

        ContentHandler osis = new PrettySerializingContentHandler(FormatType.CLASSIC_INDENT);
        osissep.provideSAXEvents(osis);

        initSource(rawText.toString(), osis.toString(), bookTextPane.getText());
    }

    public void initSource(String raw, String osis, String html) {
        rawEditorPane.setText(raw);
        osisEditorPane.setText(osis);
        htmlEditorPane.setText(html);

        rawEditorPane.setCaretPosition(0);
        osisEditorPane.setCaretPosition(0);
        htmlEditorPane.setCaretPosition(0);
    }
    
    public class ExtendedEditorPane extends JEditorPane {

        /**
         * Overriden to add antialiasing
         */
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            super.paintComponent(g);
        }
    }
}
