/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.util;

import org.jetbrains.annotations.NonNls;


/**
 * @author kir
 */
public abstract class WaitFor {
  private static final int DEFAULT_STEP = 10;
  private static final int MAX_TIMEOUT = 60 * 1000;

  private long myWaitTime;
  private boolean myInterrupted;
  private volatile boolean myConditionRealized;
  @NonNls public static final String WAIT_FOR_THREAD_NAME = "WaitFor thread";

  /** Blocking call */
  public WaitFor() {
    this(MAX_TIMEOUT);
  }

  public WaitFor(int timeoutMsecs) {
    this(timeoutMsecs, DEFAULT_STEP);
  }

  /** Blocking call */
  public WaitFor(int timeoutMsecs, final int step) {
    long started = System.currentTimeMillis();
    long deadline = timeoutMsecs == -1 ? Long.MAX_VALUE : started + timeoutMsecs;

    myConditionRealized = false;
    try {
      while(!(myConditionRealized = condition()) && System.currentTimeMillis() < deadline) {
          Thread.sleep(step);
      }
    } catch (InterruptedException e) {
      myInterrupted = true;
    }
    myWaitTime = System.currentTimeMillis() - started;
  }

  /** Non-blocking call */
  public WaitFor(final int timeoutMsecs, final Runnable toRunOnTrue) {
    new Thread(WAIT_FOR_THREAD_NAME) {
      @Override
      public void run() {
        myConditionRealized = new WaitFor(timeoutMsecs) {
          @Override
          protected boolean condition() {
            return WaitFor.this.condition();
          }
        }.isConditionRealized();

        if (myConditionRealized) {
          toRunOnTrue.run();
        }      }
    }.start();
  }

  public long getWaitedTime() {
    return myWaitTime;
  }

  public boolean isConditionRealized() {
    return myConditionRealized;
  }

  public boolean isInterrupted() {
    return myInterrupted;
  }

  protected abstract boolean condition();

  public void assertCompleted() {
    assertCompleted("");
  }
  public void assertCompleted(String message) {
    assert condition(): message;
  }
}

@@ -21,9 +21,9 @@
 -201
-4
+5
  Jet
@@ -663,16 +663,59 @@
 NonNls;%0A
+import org.jetbrains.annotations.TestOnly;%0A
 %0A%0A/**%0A *
@@ -981,21 +981,22 @@
 NonNls p
-ublic
+rivate
  static 
@@ -1048,16 +1048,43 @@
 thread%22;
+%0A  private Thread myThread;
 %0A%0A  /** 
@@ -1843,16 +1843,27 @@
 e) %7B%0A   
+ myThread =
  new Thr
@@ -2216,16 +2216,17 @@
        %7D
+%0A
       %7D%0A
@@ -2230,16 +2230,30 @@
  %7D%0A    %7D
+;%0A    myThread
 .start()
@@ -2613,24 +2613,24 @@
  message) %7B%0A
-
     assert c
@@ -2653,11 +2653,162 @@
 age;%0A  %7D
+%0A%0A  @TestOnly%0A  public void join() throws InterruptedException %7B%0A    Thread thread = myThread;%0A    if (thread != null) %7B%0A      thread.join();%0A    %7D%0A  %7D
 %0A%7D%0A

make test load-independent