/*
 * Copyright (C) 2015 DroidDriver committers
 *
 * 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 io.appium.droiddriver.util;

import android.app.Instrumentation;
import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;

import androidx.test.InstrumentationRegistry;

import io.appium.droiddriver.exceptions.DroidDriverException;
import io.appium.droiddriver.exceptions.TimeoutException;

import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/** Static utility methods pertaining to {@link Instrumentation}. */
public class InstrumentationUtils {
  private static final Runnable EMPTY_RUNNABLE =
      new Runnable() {
        @Override
        public void run() {}
      };
  private static final Executor RUN_ON_MAIN_SYNC_EXECUTOR = Executors.newSingleThreadExecutor();
  private static Instrumentation instrumentation;
  private static Bundle options;
  private static long runOnMainSyncTimeoutMillis;

  /**
   * Initializes this class. If you don't use androidx.test.runner.AndroidJUnitRunner or a
   * runner that supports {link InstrumentationRegistry}, you need to call this method
   * appropriately.
   */
  public static synchronized void init(Instrumentation instrumentation, Bundle arguments) {
    if (InstrumentationUtils.instrumentation != null) {
      throw new DroidDriverException("init() can only be called once");
    }
    InstrumentationUtils.instrumentation = instrumentation;
    options = arguments;

    String timeoutString = getD2Option("runOnMainSyncTimeout");
    runOnMainSyncTimeoutMillis = timeoutString == null ? 10_000L : Long.parseLong(timeoutString);
  }

  private static synchronized void checkInitialized() {
    if (instrumentation == null) {
      // Assume androidx.test.runner.InstrumentationRegistry is valid
      init(InstrumentationRegistry.getInstrumentation(), InstrumentationRegistry.getArguments());
    }
  }

  public static Instrumentation getInstrumentation() {
    checkInitialized();
    return instrumentation;
  }

  public static Context getTargetContext() {
    return getInstrumentation().getTargetContext();
  }

  /**
   * Gets the <a href=
   * "http://developer.android.com/tools/testing/testing_otheride.html#AMOptionsSyntax" >am
   * instrument options</a>.
   */
  public static Bundle getOptions() {
    checkInitialized();
    return options;
  }

  /** Gets the string value associated with the given key. */
  public static String getOption(String key) {
    return getOptions().getString(key);
  }

  /**
   * Calls {@link #getOption} with "dd." prefixed to {@code key}. This is for DroidDriver
   * implementation to use a consistent pattern for its options.
   */
  public static String getD2Option(String key) {
    return getOption("dd." + key);
  }

  /**
   * Tries to wait for an idle state on the main thread on best-effort basis up to {@code
   * timeoutMillis}. The main thread may not enter the idle state when animation is playing, for
   * example, the ProgressBar.
   */
  public static boolean tryWaitForIdleSync(long timeoutMillis) {
    checkNotMainThread();
    FutureTask<Void> emptyTask = new FutureTask<Void>(EMPTY_RUNNABLE, null);
    getInstrumentation().waitForIdle(emptyTask);

    try {
      emptyTask.get(timeoutMillis, TimeUnit.MILLISECONDS);
    } catch (java.util.concurrent.TimeoutException e) {
      Logs.log(
          Log.INFO,
          "Timed out after " + timeoutMillis + " milliseconds waiting for idle on main looper");
      return false;
    } catch (Throwable t) {
      throw DroidDriverException.propagate(t);
    }
    return true;
  }

  public static void runOnMainSyncWithTimeout(final Runnable runnable) {
    runOnMainSyncWithTimeout(
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            runnable.run();
            return null;
          }
        });
  }

  /**
   * Runs {@code callable} on the main thread on best-effort basis up to a time limit, which
   * defaults to {@code 10000L} and can be set as an am instrument option under the key {@code
   * dd.runOnMainSyncTimeout}.
   *
   * <p>This is a safer variation of {@link Instrumentation#runOnMainSync} because the latter may
   * hang. You may turn off this behavior by setting {@code "-e dd.runOnMainSyncTimeout 0"} on the
   * am command line.The {@code callable} may never run, for example, if the main Looper has exited
   * due to uncaught exception.
   */
  public static <V> V runOnMainSyncWithTimeout(Callable<V> callable) {
    checkNotMainThread();
    final RunOnMainSyncFutureTask<V> futureTask = new RunOnMainSyncFutureTask<>(callable);

    if (runOnMainSyncTimeoutMillis <= 0L) {
      // Call runOnMainSync on current thread without time limit.
      futureTask.runOnMainSyncNoThrow();
    } else {
      RUN_ON_MAIN_SYNC_EXECUTOR.execute(
          new Runnable() {
            @Override
            public void run() {
              futureTask.runOnMainSyncNoThrow();
            }
          });
    }

    try {
      return futureTask.get(runOnMainSyncTimeoutMillis, TimeUnit.MILLISECONDS);
    } catch (java.util.concurrent.TimeoutException e) {
      throw new TimeoutException(
          "Timed out after "
              + runOnMainSyncTimeoutMillis
              + " milliseconds waiting for Instrumentation.runOnMainSync",
          e);
    } catch (Throwable t) {
      throw DroidDriverException.propagate(t);
    } finally {
      futureTask.cancel(false);
    }
  }

  public static void checkMainThread() {
    if (Looper.myLooper() != Looper.getMainLooper()) {
      throw new DroidDriverException("This method must be called on the main thread");
    }
  }

  public static void checkNotMainThread() {
    if (Looper.myLooper() == Looper.getMainLooper()) {
      throw new DroidDriverException("This method cannot be called on the main thread");
    }
  }

  private static class RunOnMainSyncFutureTask<V> extends FutureTask<V> {
    public RunOnMainSyncFutureTask(Callable<V> callable) {
      super(callable);
    }

    public void runOnMainSyncNoThrow() {
      try {
        getInstrumentation().runOnMainSync(this);
      } catch (Throwable e) {
        setException(e);
      }
    }
  }
}
