package de.duehl.swing.ui.handler;

/*
 * Copyright 2016 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.Transferable;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;

import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.TransferHandler;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;

/**
 * Diese Klasse hilft bei dem Problem, dass beim Kopieren von in einer
 * JEditorPane angezeigtem Text und Einfügen in eine JTextPane die
 * Zeilenumbrüche verschwinden.
 *
 * Vergleiche http://stackoverflow.com/questions/7745087/
 * making-a-jeditorpane-with-html-put-correctly-formatted-text-in-clipboard
 *
 * @version 1.01     2015-10-13
 * @author Christian Dühl
 */

public class HtmlCopyPasteTransferHandler extends TransferHandler {

    private static final long serialVersionUID = 7805226589998101946L;

    @Override
    protected Transferable createTransferable(JComponent c) {
        final JEditorPane pane = (JEditorPane) c;
        final String htmlText = getTheText(pane);
        final String plainText = extractText(new StringReader(htmlText));
        return new HtmlCopyPasteTransferable(plainText, htmlText);
    }

    private String getTheText(JEditorPane pane) {
        String selectedText = pane.getSelectedText();
        /*
         * Problem dabei ist, dass dieser ohne Zeilenumbrüche und ohne HTML
         * daherkommt!
         */
        if (null == selectedText) {
            return pane.getText();
        }
        else {
            System.out.println("Selected : [" + selectedText + "]");
            return pane.getText();
            //return selectedText;
        }
    }

    private String extractText(Reader reader) {
        final ArrayList<String> list = new ArrayList<String>();

        HTMLEditorKit.ParserCallback parserCallback = new HTMLEditorKit.ParserCallback() {
            @Override
            public void handleText(final char[] data, final int pos) {
                list.add(new String(data));
            }

            @Override
            public void handleStartTag(HTML.Tag tag,
                    MutableAttributeSet attribute, int pos) {
            }

            @Override
            public void handleEndTag(HTML.Tag t, final int pos) {
            }

            @Override
            public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a,
                    final int pos) {
                if (t.equals(HTML.Tag.BR)) {
                    list.add("\n");
                }
            }

            @Override
            public void handleComment(final char[] data, final int pos) {
            }

            @Override
            public void handleError(final String errMsg, final int pos) {
            }
        };
        try {
            new ParserDelegator().parse(reader, parserCallback, true);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        String result = "";
        for (String s : list) {
            result += s;
        }
        return result;
    }

    @Override
    public void exportToClipboard(JComponent comp, Clipboard clip, int action)
            throws IllegalStateException {
        if (action == COPY) {
            clip.setContents(this.createTransferable(comp), null);
        }
    }

    @Override
    public int getSourceActions(JComponent c) {
        return COPY;
    }

}
