public boolean waitForIdle() {
      if (isRunning()) {
        synchronized (idleSync) {
          while (!idle) {
            try {
              idleSync.wait();
            } catch (InterruptedException e) {
              return false;
            }
          }
        }

        if ((handler != null) &&
            (handler.getLooper() != null) &&
            (handler.getLooper() != Looper.myLooper())) {
          // If the callbacks are posted to a different thread than this one, we can wait until all callbacks have
          // called before returning. If we don't use a Handler at all, the callbacks are already called before we
          // get here. If we do use a Handler but we use the same Looper, waiting here would actually block the
          // callbacks from being called

          synchronized (callbackSync) {
            while (callbacks > 0) {
              try {
                callbackSync.wait();
              } catch (InterruptedException e) {
                return false;
              }
            }
          }
        }
      }

      return true;
    }
<p>Wait for idle state. As this is a blocking call, you should not call it from the main UI thread. If you do
so and debug mode is enabled, this method will intentionally crash your app.</p>

<p>If not interrupted, this method will not return until all commands have finished executing. Note that this
does not necessarily mean that all the callbacks have fired yet.</p>

<p>If no Handler is used, all callbacks will have been executed when this method returns. If a Handler is
used, and this method is called from a different thread than associated with the Handler's Looper, all
callbacks will have been executed when this method returns as well. If however a Handler is used but this
method is called from the same thread as associated with the Handler's Looper, there is no way to know.</p>

<p>In practice this means that in most simple cases all callbacks will have completed when this method
returns, but if you actually depend on this behavior, you should make certain this is indeed the case.</p>

<p>See {@link Shell.Interactive} for further details on threading and handlers</p>

@return True if wait complete, false if wait interrupted
imitate/src/main/java/com/engineer/imitate/shell/Shell.java