/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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 android.test;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import junit.framework.TestCase;

/**
 * A test case that has access to {@link Instrumentation}.
 *
 * @deprecated Use
 * <a href="{@docRoot}reference/android/support/test/InstrumentationRegistry.html">
 * InstrumentationRegistry</a> instead. New tests should be written using the
 * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
 */
@Deprecated
public class InstrumentationTestCase extends TestCase {

    private Instrumentation mInstrumentation;

    /**
     * Injects instrumentation into this test case. This method is
     * called by the test runner during test setup.
     *
     * @param instrumentation the instrumentation to use with this instance
     */
    public void injectInstrumentation(Instrumentation instrumentation) {
        mInstrumentation = instrumentation;
    }

    /**
     * Injects instrumentation into this test case. This method is
     * called by the test runner during test setup.
     *
     * @param instrumentation the instrumentation to use with this instance
     *
     * @deprecated Incorrect spelling,
     * use {@link #injectInstrumentation(android.app.Instrumentation)} instead.
     */
    @Deprecated
    public void injectInsrumentation(Instrumentation instrumentation) {
        injectInstrumentation(instrumentation);
    }

    /**
     * Inheritors can access the instrumentation using this.
     * @return instrumentation
     */
    public Instrumentation getInstrumentation() {
        return mInstrumentation;
    }

    /**
     * Utility method for launching an activity.  
     * 
     * <p>The {@link Intent} used to launch the Activity is:
     *  action = {@link Intent#ACTION_MAIN}
     *  extras = null, unless a custom bundle is provided here
     * All other fields are null or empty.
     * 
     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
     * file.  This is not necessarily the same as the java package name.
     *
     * @param pkg The package hosting the activity to be launched.
     * @param activityCls The activity class to launch.
     * @param extras Optional extra stuff to pass to the activity.
     * @return The activity, or null if non launched.
     */
    public final <T extends Activity> T launchActivity(
            String pkg,
            Class<T> activityCls,
            Bundle extras) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        if (extras != null) {
            intent.putExtras(extras);
        }
        return launchActivityWithIntent(pkg, activityCls, intent);
    }

    /**
     * Utility method for launching an activity with a specific Intent.
     * 
     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
     * file.  This is not necessarily the same as the java package name.
     *
     * @param pkg The package hosting the activity to be launched.
     * @param activityCls The activity class to launch.
     * @param intent The intent to launch with
     * @return The activity, or null if non launched.
     */
    @SuppressWarnings("unchecked")
    public final <T extends Activity> T launchActivityWithIntent(
            String pkg,
            Class<T> activityCls,
            Intent intent) {
        intent.setClassName(pkg, activityCls.getName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        T activity = (T) getInstrumentation().startActivitySync(intent);
        getInstrumentation().waitForIdleSync();
        return activity;
    }
    
    /**
     * Helper for running portions of a test on the UI thread.
     * 
     * Note, in most cases it is simpler to annotate the test method with 
     * {@link android.test.UiThreadTest}, which will run the entire test method on the UI thread.
     * Use this method if you need to switch in and out of the UI thread to perform your test.
     * 
     * @param r runnable containing test code in the {@link Runnable#run()} method
     */
    public void runTestOnUiThread(final Runnable r) throws Throwable {
        final Throwable[] exceptions = new Throwable[1];
        getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                try {
                    r.run();
                } catch (Throwable throwable) {
                    exceptions[0] = throwable;
                }
            }
        });
        if (exceptions[0] != null) {
            throw exceptions[0];
        }
    }

    /**
     * Runs the current unit test. If the unit test is annotated with
     * {@link android.test.UiThreadTest}, the test is run on the UI thread.
     */
    @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 runCount = 1;
        boolean isRepetitive = false;
        if (method.isAnnotationPresent(FlakyTest.class)) {
            runCount = method.getAnnotation(FlakyTest.class).tolerance();
        } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
            runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
            isRepetitive = true;
        }

        if (method.isAnnotationPresent(UiThreadTest.class)) {
            final int tolerance = runCount;
            final boolean repetitive = isRepetitive;
            final Method testMethod = method;
            final Throwable[] exceptions = new Throwable[1];
            getInstrumentation().runOnMainSync(new Runnable() {
                public void run() {
                    try {
                        runMethod(testMethod, tolerance, repetitive);
                    } catch (Throwable throwable) {
                        exceptions[0] = throwable;
                    }
                }
            });
            if (exceptions[0] != null) {
                throw exceptions[0];
            }
        } else {
            runMethod(method, runCount, isRepetitive);
        }
    }

    // For backwards-compatibility after adding isRepetitive
    private void runMethod(Method runMethod, int tolerance) throws Throwable {
        runMethod(runMethod, tolerance, false);
    }

    private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
        Throwable exception = null;

        int runCount = 0;
        do {
            try {
                runMethod.invoke(this, (Object[]) null);
                exception = null;
            } catch (InvocationTargetException e) {
                e.fillInStackTrace();
                exception = e.getTargetException();
            } catch (IllegalAccessException e) {
                e.fillInStackTrace();
                exception = e;
            } finally {
                runCount++;
                // Report current iteration number, if test is repetitive
                if (isRepetitive) {
                    Bundle iterations = new Bundle();
                    iterations.putInt("currentiterations", runCount);
                    getInstrumentation().sendStatus(2, iterations);
                }
            }
        } while ((runCount < tolerance) && (isRepetitive || exception != null));

        if (exception != null) {
            throw exception;
        }
    }

    /**
     * Sends a series of key events through instrumentation and waits for idle. The sequence
     * of keys is a string containing the key names as specified in KeyEvent, without the
     * KEYCODE_ prefix. For instance: sendKeys("DPAD_LEFT A B C DPAD_CENTER"). Each key can
     * be repeated by using the N* prefix. For instance, to send two KEYCODE_DPAD_LEFT, use
     * the following: sendKeys("2*DPAD_LEFT").
     *
     * @param keysSequence The sequence of keys.
     */
    public void sendKeys(String keysSequence) {
        final String[] keys = keysSequence.split(" ");
        final int count = keys.length;

        final Instrumentation instrumentation = getInstrumentation();

        for (int i = 0; i < count; i++) {
            String key = keys[i];
            int repeater = key.indexOf('*');

            int keyCount;
            try {
                keyCount = repeater == -1 ? 1 : Integer.parseInt(key.substring(0, repeater));
            } catch (NumberFormatException e) {
                Log.w("ActivityTestCase", "Invalid repeat count: " + key);
                continue;
            }

            if (repeater != -1) {
                key = key.substring(repeater + 1);
            }

            for (int j = 0; j < keyCount; j++) {
                try {
                    final Field keyCodeField = KeyEvent.class.getField("KEYCODE_" + key);
                    final int keyCode = keyCodeField.getInt(null);
                    try {
                        instrumentation.sendKeyDownUpSync(keyCode);
                    } catch (SecurityException e) {
                        // Ignore security exceptions that are now thrown
                        // when trying to send to another app, to retain
                        // compatibility with existing tests.
                    }
                } catch (NoSuchFieldException e) {
                    Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
                    break;
                } catch (IllegalAccessException e) {
                    Log.w("ActivityTestCase", "Unknown keycode: KEYCODE_" + key);
                    break;
                }
            }
        }

        instrumentation.waitForIdleSync();
    }

    /**
     * Sends a series of key events through instrumentation and waits for idle. For instance:
     * sendKeys(KEYCODE_DPAD_LEFT, KEYCODE_DPAD_CENTER).
     *
     * @param keys The series of key codes to send through instrumentation.
     */
    public void sendKeys(int... keys) {
        final int count = keys.length;
        final Instrumentation instrumentation = getInstrumentation();

        for (int i = 0; i < count; i++) {
            try {
                instrumentation.sendKeyDownUpSync(keys[i]);
            } catch (SecurityException e) {
                // Ignore security exceptions that are now thrown
                // when trying to send to another app, to retain
                // compatibility with existing tests.
            }
        }

        instrumentation.waitForIdleSync();
    }

    /**
     * Sends a series of key events through instrumentation and waits for idle. Each key code
     * must be preceded by the number of times the key code must be sent. For instance:
     * sendRepeatedKeys(1, KEYCODE_DPAD_CENTER, 2, KEYCODE_DPAD_LEFT).
     *
     * @param keys The series of key repeats and codes to send through instrumentation.
     */
    public void sendRepeatedKeys(int... keys) {
        final int count = keys.length;
        if ((count & 0x1) == 0x1) {
            throw new IllegalArgumentException("The size of the keys array must "
                    + "be a multiple of 2");
        }

        final Instrumentation instrumentation = getInstrumentation();

        for (int i = 0; i < count; i += 2) {
            final int keyCount = keys[i];
            final int keyCode = keys[i + 1];
            for (int j = 0; j < keyCount; j++) {
                try {
                    instrumentation.sendKeyDownUpSync(keyCode);
                } catch (SecurityException e) {
                    // Ignore security exceptions that are now thrown
                    // when trying to send to another app, to retain
                    // compatibility with existing tests.
                }
            }
        }

        instrumentation.waitForIdleSync();
    }
    
    /**
     * Make sure all resources are cleaned up and garbage collected before moving on to the next
     * test. Subclasses that override this method should make sure they call super.tearDown()
     * at the end of the overriding method.
     * 
     * @throws Exception
     */
    @Override
    protected void tearDown() throws Exception {
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        Runtime.getRuntime().gc();
        super.tearDown();
    }
}