package org.asciidoc.intellij.activities;

import com.intellij.ide.plugins.CannotUnloadPluginException;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.util.messages.MessageBusConnection;
import org.asciidoc.intellij.AsciiDoc;
import org.asciidoc.intellij.AsciiDocPlugin;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;

/**
 * This takes care of unloading the plugin on uninstalls or updates.
 * WARNING: A dynamic unload will usually only succeed when the application is NOT in debug mode;
 * classes might be marked as "JNI Global" due to this, and not reclaimed, and then unloading fails.
 */
public class AsciiDocHandleUnloadActivity implements StartupActivity, DumbAware {

  private static final com.intellij.openapi.diagnostic.Logger LOG =
    com.intellij.openapi.diagnostic.Logger.getInstance(AsciiDocHandleUnloadActivity.class);

  private static boolean setupComplete;

  @Override
  public void runActivity(@NotNull Project project) {
    setupListener();
  }

  public static synchronized void setupListener() {
    if (!setupComplete) {
      setupComplete = true;
      LOG.info("setup of subscription");
      Application application = ApplicationManager.getApplication();
      if (application != null) {
        // check application first to don't interfere with unit tests, as this is not initialized for Unit tests
        MessageBusConnection busConnection = application.getMessageBus().connect();
        busConnection.subscribe(DynamicPluginListener.TOPIC, new DynamicPluginListener() {
          @Override
          public void checkUnloadPlugin(@NotNull IdeaPluginDescriptor pluginDescriptor) throws CannotUnloadPluginException {
            if (pluginDescriptor.getPluginId() != null
              && Objects.equals(pluginDescriptor.getPluginId().getIdString(), AsciiDocPlugin.PLUGIN_ID)) {
              LOG.info("checkUnloadPlugin");
              // https://github.com/asciidoctor/asciidoctor-intellij-plugin/issues/512
              // another reason: on windows even after unloading JAR file of the plugin still be locked and can't be deleted, making uninstall impossible
              // https://youtrack.jetbrains.com/issue/IDEA-244471
              // Update: IDEA-244471 might no be relevant here as the plugin will have the version number in the JAR file, therefore a change file will have a new name
              throw new CannotUnloadPluginException("unloading mechanism is not safe, incomplete unloading might lead to strange exceptions");
              // AsciiDoc.checkUnloadPlugin();
            }
          }

          @Override
          public void beforePluginUnload(@NotNull IdeaPluginDescriptor pluginDescriptor, boolean isUpdate) {
            if (pluginDescriptor.getPluginId() != null
              && Objects.equals(pluginDescriptor.getPluginId().getIdString(), AsciiDocPlugin.PLUGIN_ID)) {
              LOG.info("beforePluginUnload");
              AsciiDoc.beforePluginUnload();
              busConnection.dispose();
            }
          }
        });
      }
    }
  }

}

@@ -1689,16 +1689,58 @@
 t tests%0A
+        application.invokeLater(() -%3E %7B%0A  
         
@@ -1811,24 +1811,26 @@
 .connect();%0A
+  
         busC
@@ -1910,32 +1910,34 @@
 r() %7B%0A          
+  
 @Override%0A      
@@ -1922,32 +1922,34 @@
       @Override%0A
+  
           public
@@ -2057,16 +2057,18 @@
 ption %7B%0A
+  
         
@@ -2120,32 +2120,34 @@
 l%0A              
+  
 && Objects.equal
@@ -2215,32 +2215,34 @@
 n.PLUGIN_ID)) %7B%0A
+  
               LO
@@ -2276,32 +2276,34 @@
 ;%0A              
+  
 // https://githu
@@ -2373,16 +2373,18 @@
         
+ 
+ 
 // anoth
@@ -2515,16 +2515,18 @@
 ossible%0A
+  
         
@@ -2597,16 +2597,18 @@
         
+  
 // Updat
@@ -2767,16 +2767,18 @@
         
+ 
+ 
 throw ne
@@ -2912,16 +2912,18 @@
         
+  
 // Ascii
@@ -2951,32 +2951,34 @@
 ();%0A            
+  
 %7D%0A          %7D%0A%0A 
@@ -2973,19 +2973,23 @@
         
+ 
+ 
 %7D%0A%0A
+  
         
@@ -2992,32 +2992,34 @@
       @Override%0A
+  
           public
@@ -3115,32 +3115,34 @@
 ) %7B%0A            
+ 
+ 
 if (pluginDescri
@@ -3160,32 +3160,34 @@
 ginId() != null%0A
+  
               &&
@@ -3283,32 +3283,34 @@
 %7B%0A              
+  
 LOG.info(%22before
@@ -3321,24 +3321,26 @@
 inUnload%22);%0A
+  
             
@@ -3378,32 +3378,34 @@
 ;%0A              
+  
 busConnection.di
@@ -3409,24 +3409,40 @@
 .dispose();%0A
+              %7D%0A
             
@@ -3446,32 +3446,34 @@
    %7D%0A          %7D
+);
 %0A        %7D);%0A   

handle unexpected startup exception