// Copyright 2000-2019 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 com.intellij.openapi.util;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.SomeQueue;
import com.intellij.openapi.progress.util.BackgroundTaskUtil;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

@SomeQueue
public class ZipperUpdater {
  private final Alarm myAlarm;
  private boolean myRaised;
  private final Object myLock = new Object();
  private final int myDelay;
  private final Alarm.ThreadToUse myThreadToUse;
  private boolean myIsEmpty;

  public ZipperUpdater(final int delay, @NotNull Disposable parentDisposable) {
    myDelay = delay;
    myIsEmpty = true;
    myThreadToUse = Alarm.ThreadToUse.POOLED_THREAD;
    myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, parentDisposable);
  }

  public ZipperUpdater(final int delay, final Alarm.ThreadToUse threadToUse, @NotNull Disposable parentDisposable) {
    myDelay = delay;
    myThreadToUse = threadToUse;
    myIsEmpty = true;
    myAlarm = new Alarm(threadToUse, parentDisposable);
  }

  public void queue(@NotNull final Runnable runnable) {
    queue(runnable, false);
  }

  private void queue(@NotNull final Runnable runnable, final boolean urgent) {
    queue(runnable, urgent, false);
  }

  public void queue(@NotNull final Runnable runnable, final boolean urgent, final boolean anyModality) {
    synchronized (myLock) {
      if (myAlarm.isDisposed()) return;
      final boolean wasRaised = myRaised;
      myRaised = true;
      myIsEmpty = false;
      if (! wasRaised) {
        final Runnable request = new Runnable() {
          @Override
          public void run() {
            synchronized (myLock) {
              if (!myRaised) return;
              myRaised = false;
            }
            BackgroundTaskUtil.runUnderDisposeAwareIndicator(myAlarm, runnable);
            synchronized (myLock) {
              myIsEmpty = !myRaised;
            }
          }

          @Override
          public String toString() {
            return runnable.toString();
          }
        };
        if (Alarm.ThreadToUse.SWING_THREAD.equals(myThreadToUse)) {
          if (anyModality) {
            myAlarm.addRequest(request, urgent ? 0 : myDelay, ModalityState.any());
          } else if (!ApplicationManager.getApplication().isDispatchThread()) {
            myAlarm.addRequest(request, urgent ? 0 : myDelay, ModalityState.NON_MODAL);
          } else {
            myAlarm.addRequest(request, urgent ? 0 : myDelay);
          }
        }
        else {
          myAlarm.addRequest(request, urgent ? 0 : myDelay);
        }
      }
    }
  }

  public boolean isEmpty() {
    synchronized (myLock) {
      return myIsEmpty;
    }
  }

  public void stop() {
    myAlarm.cancelAllRequests();
  }

  @TestOnly
  public void waitForAllExecuted(long timeout, @NotNull TimeUnit unit) {
    try {
      myAlarm.waitForAllExecuted(timeout, unit);
    }
    catch (InterruptedException | ExecutionException | TimeoutException e) {
      throw new RuntimeException(e);
    }
  }
}

@@ -17,10 +17,10 @@
 0-20
-19
+20
  Jet
@@ -912,37 +912,8 @@
 Use;
-%0A  private boolean myIsEmpty;
 %0A%0A  
@@ -998,124 +998,20 @@
     
-myDelay = delay;%0A    myIsEmpty = true;%0A    myThreadToUse = Alarm.ThreadToUse.POOLED_THREAD;%0A    myAlarm = new Alarm(
+this(delay, 
 Alar
@@ -1238,30 +1238,8 @@
 se;%0A
-    myIsEmpty = true;%0A
     
@@ -1380,121 +1380,8 @@
 alse
-);%0A  %7D%0A%0A  private void queue(@NotNull final Runnable runnable, final boolean urgent) %7B%0A    queue(runnable, urgent
 , fa
@@ -1633,33 +1633,8 @@
 ue;%0A
-      myIsEmpty = false;%0A
     
@@ -1640,17 +1640,16 @@
    if (!
- 
 wasRaise
@@ -1957,95 +1957,8 @@
 e);%0A
-            synchronized (myLock) %7B%0A              myIsEmpty = !myRaised;%0A            %7D%0A
     
@@ -2086,20 +2086,217 @@
      %7D;%0A
+%0A
     
+    addRequest(request, urgent, anyModality);%0A      %7D%0A    %7D%0A  %7D%0A%0A  private void addRequest(@NotNull Runnable request, boolean urgent, boolean anyModality) %7B%0A    int delay = urgent ? 0 : myDelay;%0A%0A
     if (
@@ -2353,28 +2353,24 @@
 e)) %7B%0A      
-    
 if (anyModal
@@ -2372,28 +2372,24 @@
 Modality) %7B%0A
-    
         myAl
@@ -2412,32 +2412,17 @@
 equest, 
-urgent ? 0 : myD
+d
 elay, Mo
@@ -2442,30 +2442,32 @@
 ny());%0A     
+ %7D%0A
      
-%7D
  else if (!A
@@ -2523,36 +2523,32 @@
 ad()) %7B%0A        
-    
 myAlarm.addReque
@@ -2559,32 +2559,17 @@
 equest, 
-urgent ? 0 : myD
+d
 elay, Mo
@@ -2601,22 +2601,24 @@
     
+ %7D%0A
      
-%7D
  else %7B%0A
     
@@ -2609,28 +2609,24 @@
      else %7B%0A
-    
         myAl
@@ -2649,32 +2649,17 @@
 equest, 
-urgent ? 0 : myD
+d
 elay);%0A 
@@ -2667,28 +2667,16 @@
     
- 
-   %7D%0A    
+%7D%0A
     %7D%0A
-    
     
@@ -2684,28 +2684,24 @@
 lse %7B%0A      
-  
-  
 myAlarm.addR
@@ -2720,139 +2720,14 @@
 st, 
-urgent ? 0 : myDelay);%0A        %7D%0A      %7D%0A    %7D%0A  %7D%0A%0A  public boolean isEmpty() %7B%0A    synchronized (myLock) %7B%0A      return myIsEmpty
+delay)
 ;%0A  

Refactor "ZipperUpdater" - remove unused, cleanup