/*
 * Copyright (C) 2013 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.helpers;

import android.app.Activity;
import android.content.Context;
import android.os.Debug;
import android.test.FlakyTest;
import android.util.Log;

import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import io.appium.droiddriver.DroidDriver;
import io.appium.droiddriver.exceptions.UnrecoverableException;
import io.appium.droiddriver.util.FileUtils;
import io.appium.droiddriver.util.Logs;

/**
 * Base class for tests using DroidDriver that reports uncaught exceptions, for * example OOME,
 * instead of crash. Also supports other features, including taking screenshot on failure. It is NOT
 * required, but provides handy features.
 */
public abstract class BaseDroidDriverTest<T extends Activity> extends
    D2ActivityInstrumentationTestCase2<T> {

  private static boolean classSetUpDone = false;
  // In case of device-wide fatal errors, e.g. OOME, the remaining tests will
  // fail and the messages will not help, so skip them.
  private static boolean skipRemainingTests = false;
  // Store uncaught exception from AUT.
  private static volatile Throwable uncaughtException;
  static {
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
      @Override
      public void uncaughtException(Thread thread, Throwable ex) {
        uncaughtException = ex;
        // In most cases uncaughtException will be reported by onFailure().
        // But if it occurs in InstrumentationTestRunner, it's swallowed.
        // Always log it for all cases.
        Logs.log(Log.ERROR, uncaughtException, "uncaughtException");
      }
    });
  }

  protected DroidDriver driver;

  protected BaseDroidDriverTest(Class<T> activityClass) {
    super(activityClass);
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    if (!classSetUpDone) {
      classSetUp();
      classSetUpDone = true;
    }
    driver = DroidDrivers.get();
  }

  @Override
  protected void tearDown() throws Exception {
    super.tearDown();
    driver = null;
  }

  protected Context getTargetContext() {
    return getInstrumentation().getTargetContext();
  }

  /**
   * Initializes test fixture once for all tests extending this class. This may have unexpected
   * behavior - if multiple subclasses override this method, only the first override is executed.
   * Other overrides are silently ignored. You can either use {@link SingleRun} in {@link #setUp},
   * or override this method, which is a simpler alternative with the aforementioned catch.
   */
  protected void classSetUp() {
    DroidDriversInitializer.get(DroidDrivers.newDriver()).singleRun();
  }

  protected boolean reportSkippedAsFailed() {
    return false;
  }

  protected void skip() {
    if (reportSkippedAsFailed()) {
      fail("Skipped due to prior failure");
    }
  }

  /**
   * Hook for handling failure, for example, taking a screenshot.
   */
  protected void onFailure(Throwable failure) throws Throwable {
    // If skipRemainingTests is true, the failure has already been reported.
    if (skipRemainingTests) {
      return;
    }
    if (shouldSkipRemainingTests(failure)) {
      skipRemainingTests = true;
    }

    // Give uncaughtException (thrown by AUT instead of tests) high priority
    if (uncaughtException != null) {
      failure = uncaughtException;
    }

    try {
      if (failure instanceof OutOfMemoryError) {
        dumpHprof();
      } else if (uncaughtException == null) {
        String baseFileName = getBaseFileName();
        driver.dumpUiElementTree(baseFileName + ".xml");
        driver.getUiDevice().takeScreenshot(baseFileName + ".png");
      }
    } catch (Throwable e) {
      // This method is for troubleshooting. Do not throw new error; we'll
      // throw the original failure.
      Logs.log(Log.WARN, e);
      if (e instanceof OutOfMemoryError && !(failure instanceof OutOfMemoryError)) {
        skipRemainingTests = true;
        try {
          dumpHprof();
        } catch (Throwable ignored) {
        }
      }
    }

    throw failure;
  }

  protected boolean shouldSkipRemainingTests(Throwable e) {
    return e instanceof UnrecoverableException || e instanceof OutOfMemoryError
        || skipRemainingTests || uncaughtException != null;
  }

  /**
   * Gets the base filename for troubleshooting files. For example, a screenshot
   * is saved in the file "basename".png.
   */
  protected String getBaseFileName() {
    return "dd/" + getClass().getSimpleName() + "." + getName();
  }

  protected void dumpHprof() throws IOException {
    String path = FileUtils.getAbsoluteFile(getBaseFileName() + ".hprof").getPath();
    // create an empty readable file
    FileUtils.open(path).close();
    Debug.dumpHprofData(path);
  }

  /**
   * Fixes JUnit3: always call tearDown even when setUp throws. Also adds the
   * {@link #onFailure} hook.
   */
  @Override
  public void runBare() throws Throwable {
    if (skipRemainingTests) {
      skip();
      return;
    }
    if (uncaughtException != null) {
      onFailure(uncaughtException);
    }

    Throwable exception = null;
    try {
      setUp();
      runTest();
    } catch (Throwable runException) {
      exception = runException;
      // ActivityInstrumentationTestCase2.tearDown() finishes activity
      // created by getActivity(), so call this before tearDown().
      onFailure(exception);
    } finally {
      try {
        tearDown();
      } catch (Throwable tearDownException) {
        if (exception == null) {
          exception = tearDownException;
        }
      }
    }
    if (exception != null) {
      throw exception;
    }
  }

  /**
   * Overrides to fail fast when the test is annotated as   FlakyTest and we should skip remaining
   * tests (the failure is fatal). Most lines are copied from super classes.
   * <p>
   * When a flaky test is re-run, tearDown() and setUp() are called first in order to reset state.
   */
  @Override
  protected void runTest() throws Throwable {
    String fName = getName();
    assertNotNull(fName);
    Method method = null;
    try {
      // use getMethod to get all public inherited
      // methods. getDeclaredMethods returns all
      // methods of this class but excludes the
      // inherited ones.
      method = getClass().getMethod(fName, (Class[]) null);
    } catch (NoSuchMethodException e) {
      fail("Method \"" + fName + "\" not found");
    }

    if (!Modifier.isPublic(method.getModifiers())) {
      fail("Method \"" + fName + "\" should be public");
    }

    int tolerance = 1;
    if (method.isAnnotationPresent(FlakyTest.class)) {
      tolerance = method.getAnnotation(FlakyTest.class).tolerance();
    }

    for (int runCount = 0; runCount < tolerance; runCount++) {
      if (runCount > 0) {
        Logs.logfmt(Log.INFO, "Running %s round %d of %d attempts", fName, runCount + 1, tolerance);
        // We are re-attempting a test, so reset all state.
        tearDown();
        setUp();
      }

      try {
        method.invoke(this);
        return;
      } catch (InvocationTargetException e) {
        e.fillInStackTrace();
        Throwable exception = e.getTargetException();
        if (shouldSkipRemainingTests(exception) || runCount >= tolerance - 1) {
          throw exception;
        }
        Logs.log(Log.WARN, exception);
      } catch (IllegalAccessException e) {
        e.fillInStackTrace();
        throw e;
      }
    }
  }
}
