package com.reason.ide;

import com.intellij.AppTopics;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.messages.MessageBusConnection;
import com.reason.ide.format.ReformatOnSave;
import com.reason.ide.hints.RmlDocumentListener;
import com.reason.insight.InsightManager;
import com.reason.insight.InsightManagerImpl;
import com.reason.insight.RincewindDownloader;

import java.io.File;

import static com.reason.Platform.getOsPrefix;

public class ReasonProjectTracker extends AbstractProjectComponent {

    private final Logger m_log = Logger.getInstance("ReasonML");

    private RmlDocumentListener m_documentListener;
    private MessageBusConnection m_messageBusConnection;
    private VirtualFileListener m_vfListener;

    protected ReasonProjectTracker(Project project) {
        super(project);
    }

    @Override
    public void projectOpened() {
        if (SystemInfo.is64Bit) {
            // Try to locate Rincewind
            if (!getOsPrefix().isEmpty()) {
                InsightManagerImpl insightManager = (InsightManagerImpl) myProject.getComponent(InsightManager.class);
                File rincewindFile = insightManager.getRincewindFile();
                if (rincewindFile.exists()) {
                    m_log.info("Found " + rincewindFile);
                    insightManager.isDownloaded.set(true);
                } else {
                    m_log.info("Downloading " + rincewindFile.getName() + "...");
                    RincewindDownloader downloadingTask = RincewindDownloader.getInstance(myProject);
                    ProgressManager.getInstance().run(downloadingTask);
                }
            }
        } else {
            m_log.info("32Bit system detected, can't use rincewind");
        }

        m_documentListener = new RmlDocumentListener(myProject);
        EditorFactory.getInstance().getEventMulticaster().addDocumentListener(m_documentListener);

        m_messageBusConnection = myProject.getMessageBus().connect();
        m_messageBusConnection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new RmlFileEditorListener(myProject));
        m_messageBusConnection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new ReformatOnSave(myProject));

        m_vfListener = new VirtualFileListener(myProject);
        VirtualFileManager.getInstance().addVirtualFileListener(m_vfListener);
    }

    @Override
    public void projectClosed() {
        EditorFactory.getInstance().getEventMulticaster().removeDocumentListener(m_documentListener);
        VirtualFileManager.getInstance().removeVirtualFileListener(m_vfListener);
        if (m_messageBusConnection != null) {
            m_messageBusConnection.disconnect();
        }
    }

}

@@ -759,16 +759,50 @@
 oader;%0A%0A
+import javax.annotation.Nullable;%0A
 import j
@@ -995,24 +995,38 @@
 easonML%22);%0A%0A
+    @Nullable%0A
     private 
@@ -1065,16 +1065,30 @@
 stener;%0A
+    @Nullable%0A
     priv
@@ -1136,16 +1136,30 @@
 ection;%0A
+    @Nullable%0A
     priv
@@ -2867,24 +2867,70 @@
 tClosed() %7B%0A
+        if (m_documentListener != null) %7B%0A    
         Edit
@@ -3011,32 +3011,82 @@
 umentListener);%0A
+        %7D%0A        if (m_vfListener != null) %7B%0A    
         VirtualF
@@ -3143,32 +3143,42 @@
 (m_vfListener);%0A
+        %7D%0A
         if (m_me

add nullable