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

package kiyut.alkitab.windows;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkEvent.EventType;
import javax.swing.event.HyperlinkListener;
import kiyut.alkitab.actions.GoNextAction;
import kiyut.alkitab.actions.GoPreviousAction;
import kiyut.alkitab.actions.ReloadAction;
import kiyut.alkitab.bookviewer.BookViewer;
import kiyut.alkitab.bookviewer.BookViewerManager;
import kiyut.alkitab.bookviewer.BookViewerNode;
import kiyut.alkitab.bookviewer.SingleBookViewerPane;
import kiyut.alkitab.bookviewer.SwordURI;
import kiyut.alkitab.history.History;
import kiyut.alkitab.history.HistoryManager;
import kiyut.alkitab.util.ComponentOrientationSupport;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.passage.Key;
import org.openide.awt.StatusDisplayer;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallbackSystemAction;
import org.openide.util.actions.SystemAction;
import org.openide.windows.TopComponent;

/**
 * TopComponent which displays {@link kiyut.alkitab.bookviewer.SingleBookViewerPane SingleBookViewerPane}.
 * 
 * @author Tonny Kohar <tonny.kohar@gmail.com>
 */
public class SingleBookTopComponent extends BookViewerTopComponent {
    
    /** path to the icon used by the component and its open action */
//    static final String ICON_PATH = "SET/PATH/TO/ICON/HERE";

    private static final String PREFERRED_ID = "SingleBookTopComponent";
    
    private SingleBookViewerPane bookViewer;

    private Action goPreviousDelegateAction;
    private Action goNextDelegateAction;
    
    public SingleBookTopComponent() {
        initComponents();
        setName(NbBundle.getMessage(SingleBookTopComponent.class, "CTL_SingleBookTopComponent"));
        setToolTipText(NbBundle.getMessage(SingleBookTopComponent.class, "HINT_SingleBookTopComponent"));
//        setIcon(Utilities.loadImage(ICON_PATH, true));
        
        initCustom();

        ComponentOrientationSupport.applyComponentOrientation(this);
    }

    /** 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() {

        setLayout(new java.awt.BorderLayout());
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_ONLY_OPENED;
    }

    @Override
    protected String preferredID() {
        return PREFERRED_ID;
    }
    
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        super.writeExternal(out);
        
        List<Book> books = bookViewer.getBooks();
        String bookName = books.get(0).getInitials();
        
        out.writeObject(bookName);
        out.writeObject(bookViewer.getKey());
    }
    
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        super.readExternal(in);
        
        String bookName = (String)in.readObject();
        Key key = (Key)in.readObject();
        
        bookViewer.setBook(bookName);
        bookViewer.setKey(key);        
        bookViewer.reload();
    }
    
    /** If you override this, please make sure to call super.initCustom() */
    protected void initCustom() {
        bookViewer = new SingleBookViewerPane() {
            @Override
            public void reload() {
                super.reload();
                updateHistoryAction();
            }
        };
        add(BorderLayout.CENTER,(JComponent)bookViewer);
        
        bookViewerNode = new BookViewerNode(bookViewer);
        
        bookViewer.addPropertyChangeListener(BookViewer.VIEWER_NAME, new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                String name = (String)evt.getNewValue();
                setName(name);
                setToolTipText(name);
            }
        });
        
        bookViewer.addHyperlinkListener(new HyperlinkListener() {
            @Override
            public void hyperlinkUpdate(HyperlinkEvent evt) {
                SingleBookTopComponent.this.hyperlinkUpdate(evt);
                
            }
        });
        
        ActionMap actionMap = getActionMap();

        CallbackSystemAction goPreviousAction = SystemAction.get(GoPreviousAction.class);
        CallbackSystemAction goNextAction = SystemAction.get(GoNextAction.class);
        CallbackSystemAction reloadAction = SystemAction.get(ReloadAction.class);

        goPreviousDelegateAction = new GoPreviousDelegateAction();
        goNextDelegateAction = new GoNextDelegateAction();

        actionMap.put(goPreviousAction.getActionMapKey(), goPreviousDelegateAction);
        actionMap.put(goNextAction.getActionMapKey(), goNextDelegateAction);
        actionMap.put(reloadAction.getActionMapKey(), new ReloadDelegateAction());
    }
    
    @Override
    public void openURI(SwordURI uri, String info) {
        bookViewer.openURI(uri);
    }
    
    @Override
    public BookViewer getBookViewer() {
        return bookViewer;
    }
    
    private void hyperlinkUpdate(HyperlinkEvent evt) {
        EventType eventType = evt.getEventType();
        String uri = evt.getDescription();
        SwordURI swordURI = SwordURI.createURI(uri);
        
        if (swordURI == null) {
            Logger logger = Logger.getLogger(DefinitionsTopComponent.class.getName());
            logger.log(Level.WARNING, "invalid SwordURI: {0}", uri);
            return;
        }
        
        if (eventType.equals(HyperlinkEvent.EventType.ACTIVATED)) {
            String fragment = swordURI.getFragment();
            if (fragment.length() > 0) {
                if (fragment.charAt(0) == '#') {
                    return;
                }
            }
            
            BookViewerManager.getInstance().openURI(swordURI);
        } else if (eventType.equals(HyperlinkEvent.EventType.ENTERED)) {
            //StatusDisplayer.getDefault().setStatusText(uri);
            StatusDisplayer.getDefault().setStatusText(swordURI.toString());
        }
    }

    /**
     * Update history related UI action state eg: setEnabled(true/false)
     * This methods is called after {@link kiyut.alkitab.api.BookViewer#reload()} called
     */
    protected void updateHistoryAction() {
        HistoryManager historyManager = bookViewer.getHistoryManager();

        History hist = historyManager.current();
        if (hist == null) {
            goPreviousDelegateAction.setEnabled(false);
            goNextDelegateAction.setEnabled(false);
        } else {
            goPreviousDelegateAction.setEnabled(hist.hasPrevious());
            goNextDelegateAction.setEnabled(hist.hasNext());
        }
    }

    public class GoNextDelegateAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent evt) {
            bookViewer.goNext();
        }
    }

    public class GoPreviousDelegateAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent evt) {
            bookViewer.goPrevious();
        }
    }

    public class ReloadDelegateAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent evt) {
            bookViewer.reload();
        }
    }

}
