/*
 * Copyright 2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.alexfalappa.nbspringboot.projects;

import com.github.alexfalappa.nbspringboot.Utils;
import java.awt.EventQueue;
import java.awt.Image;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import javax.swing.event.ChangeListener;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.api.project.Project;
import org.netbeans.spi.project.ProjectIconAnnotator;
import org.openide.util.ChangeSupport;
import org.openide.util.ImageUtilities;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.ServiceProvider;

/**
 * Add badge to project icon of Spring Boot projects.
 * <p>
 * Based on project icon annotator for JavaFX projects in NetBeans:
 * javafx/javafx2.project/src/org/netbeans/modules/javafx2/project/JFXProjectIconAnnotator.java
 *
 * @author Alessandro Falappa
 * @author Hector Espert
 * @author Diego Díez Ricondo
 */
@ServiceProvider(service = ProjectIconAnnotator.class, position = 10)
public class SpringBootProjectIconAnnotator implements ProjectIconAnnotator {

    @StaticResource
    private static final String BOOT_PROJECT_BADGE_PATH = "com/github/alexfalappa/nbspringboot/projects/springboot-badge.png";    //NOI18N
    private static final URL BOOT_PROJECT_BADGE_URL = SpringBootProjectIconAnnotator.class.getClassLoader().getResource(BOOT_PROJECT_BADGE_PATH);
    private static final Image BOOT_PROJECT_BADGE_IMG = ImageUtilities.loadImage(BOOT_PROJECT_BADGE_PATH);
    private static final String BOOT_PROJECT_TOOLTIP_TEXT = "Spring Boot application";
    private final ChangeSupport cs = new ChangeSupport(this);
    private final Map<Project, Boolean> projectsMap = Collections.synchronizedMap(new WeakHashMap<>());

    @Override
    public Image annotateIcon(final Project p, Image original, final boolean openedNode) {
        Image annotated = original;
        Boolean type = projectsMap.get(p);
        // TODO: once the project is detected as spring-boot is not evaluated anymore until netbeans restart
        if (type != null && type == true) {
            String tooltip = ImageUtilities.getImageToolTip(original);
            if (!tooltip.contains(BOOT_PROJECT_TOOLTIP_TEXT)) {
                final String htmlMessage = "<img src=\"" //NOI18N
                        + BOOT_PROJECT_BADGE_URL.toExternalForm()
                        + "\">&nbsp;" //NOI18N
                        + BOOT_PROJECT_TOOLTIP_TEXT;
                annotated = ImageUtilities.mergeImages(
                        ImageUtilities.addToolTipToImage(original, htmlMessage),
                        BOOT_PROJECT_BADGE_IMG,
                        7, 7);
            }
        } else {
            evaluateProject(p);
        }
        return annotated;
    }

    @Override
    public void addChangeListener(ChangeListener listener) {
        cs.addChangeListener(listener);
    }

    @Override
    public void removeChangeListener(ChangeListener listener) {
        cs.removeChangeListener(listener);
    }

    public void fireChange(final Project p, boolean type) {
        projectsMap.put(p, type);
        cs.fireChange();
    }

    private void evaluateProject(final Project prj) {
        final Runnable runEvaluateProject = () -> {
            boolean flag = Utils.isSpringBootProject(prj);
            projectsMap.put(prj, flag);
            if (flag == true) {
                cs.fireChange();
            }
        };
        if (EventQueue.isDispatchThread()) {
            runEvaluateProject.run();
        } else {
            final RequestProcessor rp = new RequestProcessor(SpringBootProjectIconAnnotator.class.getName());
            rp.post(runEvaluateProject);
        }
    }

}

@@ -864,24 +864,89 @@
 eakHashMap;%0A
+import java.util.logging.Level;%0Aimport java.util.logging.Logger;%0A
 import javax
@@ -970,24 +970,24 @@
 geListener;%0A
-
 import org.n
@@ -2267,16 +2267,123 @@
 ation%22;%0A
+    private static final Logger logger = Logger.getLogger(SpringBootProjectIconAnnotator.class.getName());%0A
     priv
@@ -2698,20 +2698,25 @@
 Boolean 
-type
+isBootPrj
  = proje
@@ -2726,24 +2726,61 @@
 Map.get(p);%0A
+        if (isBootPrj != null) %7B%0A    
         // T
@@ -2888,44 +2888,114 @@
     
-if (type != null && type == true) %7B%0A
+    if (isBootPrj) %7B%0A                logger.log(Level.FINE, %22Annotating icon for %7B0%7D%22, p.toString());%0A    
     
@@ -3069,24 +3069,28 @@
             
+  
+  
 if (!tooltip
@@ -3141,24 +3141,28 @@
             
+    
 final String
@@ -3215,32 +3215,36 @@
                 
+ 
+   
 + BOOT_PROJECT_B
@@ -3293,16 +3293,20 @@
         
+   
+ 
 + %22%5C%22%3E&n
@@ -3312,32 +3312,36 @@
 nbsp;%22 //NOI18N%0A
+    
                 
@@ -3393,16 +3393,20 @@
         
+  
+  
 annotate
@@ -3437,16 +3437,20 @@
 Images(%0A
+    
         
@@ -3546,16 +3546,20 @@
         
+    
 BOOT_PRO
@@ -3602,15 +3602,37 @@
     
+    
 7, 7);%0A
+                %7D%0A
     
@@ -3987,134 +3987,8 @@
  %7D%0A%0A
-    public void fireChange(final Project p, boolean type) %7B%0A        projectsMap.put(p, type);%0A        cs.fireChange();%0A    %7D%0A%0A
     
@@ -4089,16 +4089,101 @@
 () -%3E %7B%0A
+            logger.log(Level.FINE, %22Evaluating icon badge for %7B0%7D%22, prj.toString());%0A
         
@@ -4363,16 +4363,16 @@
      %7D;%0A
-
         
@@ -4375,16 +4375,17 @@
     if (
+!
 EventQue

Fix project evaluation and caching in icon annotator