// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.svn;

import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.Service;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

@Service
final class SvnCompatibilityChecker {
  private final Project myProject;
  private final static long ourFrequency = 10;
  private final static long ourInvocationMax = 10;
  private final static long ourInitCounter = 3;

  private long myCounter = 0;
  private long myDownStartCounter = ourInitCounter;
  private long myInvocationCounter = 0;

  private final Object myLock = new Object();

  SvnCompatibilityChecker(@NotNull Project project) {
    myProject = project;
  }

  public void checkAndNotify(@NotNull List<VirtualFile> roots) {
    if (roots.isEmpty()) return;

    synchronized (myLock) {
      if (myInvocationCounter >= ourInvocationMax) return;
      ++myCounter;
      --myDownStartCounter;
      if ((myCounter > ourFrequency) || (myDownStartCounter >= 0)) {
        myCounter = 0;
        ++myInvocationCounter;
        final Application application = ApplicationManager.getApplication();
        application.executeOnPooledThread(() -> {
          final List<VirtualFile> suspicious = new ArrayList<>();
          for (VirtualFile vf : roots) {
            if (SvnUtil.seemsLikeVersionedDir(vf)) {
              suspicious.add(vf);
            }
          }
          if (!suspicious.isEmpty()) {
            final String message = (suspicious.size() == 1)
                                   ? "Root '" + suspicious.get(0).getPresentableName() + "' is likely to be of unsupported Subversion format"
                                   : "Some roots are likely to be of unsupported Subversion format";
            application
              .invokeLater(() -> new VcsBalloonProblemNotifier(myProject, message, MessageType.WARNING).run(), ModalityState.NON_MODAL,
                           o -> (!myProject.isOpen()) || myProject.isDisposed());
          }
        });
      }
    }
  }
}

@@ -199,91 +199,18 @@
 api.
-application.Application;%0Aimport com.intellij.openapi.application.ApplicationManager
+Disposable
 ;%0Aim
@@ -570,40 +570,387 @@
 til.
-ArrayList;%0Aimport java.util.List
+List;%0A%0Aimport static com.intellij.openapi.application.ApplicationManager.getApplication;%0Aimport static com.intellij.openapi.progress.ProgressManager.checkCanceled;%0Aimport static com.intellij.openapi.progress.util.BackgroundTaskUtil.executeOnPooledThread;%0Aimport static com.intellij.openapi.util.Disposer.isDisposed;%0Aimport static com.intellij.util.containers.ContainerUtil.filter
 ;%0A%0A@
@@ -993,16 +993,38 @@
 Checker 
+implements Disposable 
 %7B%0A  priv
@@ -1639,16 +1639,17 @@
 return;%0A
+%0A
       ++
@@ -1696,17 +1696,16 @@
      if 
-(
 (myCount
@@ -1707,17 +1707,18 @@
 Counter 
-%3E
+%3C=
  ourFreq
@@ -1726,14 +1726,12 @@
 ency
-) %7C%7C (
+ && 
 myDo
@@ -1749,19 +1749,22 @@
 ter 
-%3E= 0)) %7B%0A  
+%3C 0) return;%0A%0A
     
@@ -1780,18 +1780,16 @@
 er = 0;%0A
-  
       ++
@@ -1817,101 +1817,15 @@
     
+%7D%0A%0A
     
-final Application application = ApplicationManager.getApplication();%0A        application.
 exec
@@ -1842,16 +1842,22 @@
 dThread(
+this, 
 () -%3E %7B%0A
@@ -1862,26 +1862,16 @@
 %7B%0A      
-    final 
 List%3CVir
@@ -1884,114 +1884,67 @@
 le%3E 
-suspicious = new ArrayList%3C%3E();%0A          for (VirtualFile vf : roots) %7B%0A            if (SvnUtil.
+incompatible = filter(roots, SvnCompatibilityChecker::
 seems
-Like
 Vers
@@ -1952,135 +1952,185 @@
 oned
-Dir(vf)) %7B%0A              suspicious.add(vf
+);%0A      if (!incompatible.isEmpty()) notify(incompatible
 );%0A    
-      
+%7D);%0A
   %7D%0A
+%0A
   
-        %7D%0A          if (!suspicious.isEmpty()
+@Override%0A  public void dispose() %7B%0A  %7D%0A%0A  private void notify(@NotNull List%3CVirtualFile%3E roots
 ) %7B%0A   
-         final
  Str
@@ -2147,18 +2147,12 @@
 e = 
-(suspiciou
+root
 s.si
@@ -2164,21 +2164,9 @@
 == 1
-)%0A           
+%0A
     
@@ -2182,19 +2182,16 @@
         
-   
 ? %22Root 
@@ -2199,17 +2199,12 @@
 %22 + 
-suspiciou
+root
 s.ge
@@ -2305,30 +2305,16 @@
         
-              
 : %22Some 
@@ -2375,64 +2375,102 @@
 t%22;%0A
-            application%0A              .invokeLater(() -%3E
+%0A    getApplication().invokeLater(%0A      () -%3E %7B%0A        if (isDisposed(this)) return;%0A       
  new
@@ -2542,17 +2542,32 @@
 G).run()
-,
+;%0A      %7D,%0A     
  Modalit
@@ -2586,129 +2586,158 @@
 ODAL
-,
 %0A    
-                       o -%3E (!myProject.isOpen()) %7C%7C myProject.isDisposed());%0A          %7D%0A        %7D
+);%0A  %7D%0A%0A  private static boolean seemsVersioned(@NotNull VirtualFile root) %7B%0A    checkCanceled(
 );%0A    
-  %7D%0A    %7D
+return SvnUtil.seemsLikeVersionedDir(root);
 %0A  %7D

Refactor "SvnCompatibilityChecker" - make "Disposable", simplify