package de.duehl.swing.ui.timer;

/*
 * Copyright 2021 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 javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;

import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.dragndrop.ChangeInformer;
import de.duehl.swing.ui.highlightingeditor.multiplereactor.ChangeReactor;

/**
 * Diese Klasse überprüft ein paar Eingabefelder auf Veränderungen.
 *
 * @version 1.01     2021-03-30
 * @author Christian Dühl
 */

public class WaitingUserInputTimerForSelections extends WaitingUserInputTimerOperator
        implements ChangeReactor {

    /** Anzahl der Millisekunden vor Durchführung der Aufgabe. */
    private static final long MILLISECONDS_BEFORE_REACTION = 250;

    /** Objekt das über Änderungen an den Daten informiert wird. */
    protected final ChangeInformer changeInformer;

    /** Gibt an, ob bei Änderungen am Dokument das Syntax-Highlighting durchgeführt werden soll. */
    private boolean reactOnChanges;

    /**
     * Konstruktor.
     *
     * @param changeInformer
     *            Objekt das über Änderungen an den Daten informiert wird.
     */
    public WaitingUserInputTimerForSelections(ChangeInformer changeInformer) {
        super(MILLISECONDS_BEFORE_REACTION);
        this.changeInformer = changeInformer;
    }

    public void addJTextField(JTextField textField) {
        Document document = textField.getDocument();
        document.addDocumentListener(createWaitingDocumentListener());
    }

    public void addStringSelection(StringSelection selection) {
        selection.addTextFieldDocumentListener(createWaitingDocumentListener());
    }

    /*
     * https://stackoverflow.com/questions/15775356/
     *     how-to-get-a-documentfilter-to-work-with-a-jcombobox
     *
     *      Object editorComponent = combo.getEditor().getEditorComponent();
     *      Document document = ((JTextComponent)editorComponent).getDocument();
     *
     *      if (document instanceof PlainDocument plainDocument) {
     *          plainDocument.setDocumentFilter(new DocumentFilter() { ... }
     *      }
     *
     * Vielleicht geht das mit dem Listener analog.
     */

    /**
     * Erzeugt einen DocumentListener, der nach der Beendigung von Benutzereingaben die
     * Syntax-Hervorhebung durchführt.
     */
    private DocumentListener createWaitingDocumentListener() {
        return new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent e) {
                warnAboutUserInput();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                warnAboutUserInput();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                warnAboutUserInput();
            }
            private void warnAboutUserInput() {
                if (reactOnChanges) {
                    reactOnDocumentChanges();
                }
            }
        };
    }

    private void reactOnDocumentChanges() {
        startTimer();
    }

    /**
     * Gibt an, dass bei Änderungen am Dokument das Syntax-Highlighting durchgeführt werden soll.
     */
    @Override
    public void reactOnChanges() {
        reactOnChanges = true;
    }

    /**
     * Gibt an, dass bei Änderungen am Dokument kein Syntax-Highlighting durchgeführt werden soll.
     */
    @Override
    public void doNotReactOnChanges() {
        reactOnChanges = false;
    }

    @Override
    protected Runnable createRunnable() {
        return new Runnable() {
            @Override
            public void run() {
                SwingUtilities.invokeLater(() -> changeInformer.informAboutChangingData());
            }
        };
    }

}
