package lukazitnik.jshint.annotations;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
import lukazitnik.jshint.JSHintError;
import org.netbeans.api.editor.EditorRegistry;
import org.netbeans.modules.editor.NbEditorDocument;

public class EditorRegistryListener implements PropertyChangeListener {

    Map<NbEditorDocument, JSHintDocumentListener> history = new HashMap<>();

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        JTextComponent jtc = EditorRegistry.lastFocusedComponent();

        if (jtc == null) {
            return;
        }

        final NbEditorDocument focusedDocument = (NbEditorDocument) jtc.getDocument();
        String mimeType = (String) focusedDocument.getProperty(NbEditorDocument.MIME_TYPE_PROP);

        if (!mimeType.equals("text/javascript")) {
            return;
        }

        switch (evt.getPropertyName()) {
            case EditorRegistry.FOCUS_GAINED_PROPERTY:
                if (!history.keySet().contains(focusedDocument)) {

                    // The file has just been opened, so ...
                    addDocumentListenerAndAnnotations(focusedDocument);
                }
                break;
            case EditorRegistry.COMPONENT_REMOVED_PROPERTY:

                // Clean up history
                List<NbEditorDocument> openDocuments = getOpenJSDocuments();
                Iterator<NbEditorDocument> it = history.keySet().iterator();
                while (it.hasNext()) {
                    NbEditorDocument historicalDocument = it.next();
                    if (!openDocuments.contains(historicalDocument)) {

                        // Don't bother calling removeDocumentListenerAndAnnotations()
                        it.remove();
                    }
                }
                break;
        }
    }

    public void updateOpenDocuments() {
        List<NbEditorDocument> openDocuments = getOpenJSDocuments();
        for (NbEditorDocument d : openDocuments) {
            addDocumentListenerAndAnnotations(d);
        }
    }

    public void updateHistoryDocuments() {
        Iterator<NbEditorDocument> it = history.keySet().iterator();
        while (it.hasNext()) {
            NbEditorDocument d = it.next();
            removeDocumentListenerAndAnnotations(d);
            it.remove();
        }
    }

    private List<NbEditorDocument> getOpenJSDocuments() {
        List<NbEditorDocument> openDocuments = new ArrayList<>();
        for (JTextComponent component : EditorRegistry.componentList()) {
            NbEditorDocument d = (NbEditorDocument) component.getDocument();
            String mimeType = (String) d.getProperty(NbEditorDocument.MIME_TYPE_PROP);
            if (mimeType.equals("text/javascript")) {
                openDocuments.add(d);
            }
        }
        return openDocuments;
    }

    private void addDocumentListenerAndAnnotations(NbEditorDocument d) {
        JSHintDocumentListener dl = new JSHintDocumentListener();
        dl.updateAnnotations(d);
        d.addDocumentListener(dl);
        history.put(d, dl);
    }

    private void removeDocumentListenerAndAnnotations(NbEditorDocument d) {
        SwingUtilities.invokeLater(new Annotator(d, new LinkedList<JSHintError>()));
        d.removeDocumentListener(history.get(d));
    }

}

@@ -304,16 +304,50 @@
 lities;%0A
+import javax.swing.text.Document;%0A
 import j
@@ -879,86 +879,330 @@
     
-final NbEditorDocument focusedDocument = (NbEditorDocument) jtc.getDocument();
+Document d = jtc.getDocument(); // Normally, an instance of org.netbeans.modules.csl.core.GsfDocument%0A%0A        if (d instanceof NbEditorDocument == false) %7B%0A            // Annotations can only be added to NbEditorDocuments%0A            return;%0A        %7D%0A%0A        final NbEditorDocument nbd = (NbEditorDocument) d; // Upcast
 %0A   
@@ -1233,31 +1233,19 @@
 String) 
-focusedDocument
+nbd
 .getProp
@@ -1509,31 +1509,19 @@
 ontains(
-focusedDocument
+nbd
 )) %7B%0A%0A  
@@ -1637,23 +1637,11 @@
 ons(
-focusedDocument
+nbd
 );%0A 
@@ -3030,32 +3030,24 @@
             
-NbEditor
 Document d =
@@ -3039,24 +3039,252 @@
    Document 
+d = component.getDocument();%0A            if (d instanceof NbEditorDocument == false) %7B%0A                // Annotations can only be added to NbEditorDocuments%0A                continue;%0A            %7D%0A            NbEditorDocument nb
 d = (NbEdito
@@ -3358,16 +3358,18 @@
 String) 
+nb
 d.getPro
@@ -3496,16 +3496,18 @@
 nts.add(
+nb
 d);%0A    

handle http://statistics.netbeans.org/analytics/detail.do?id=220813