/*
 * Copyright (C) 2012 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 com.android.uiautomator.core;

import android.content.Context;
import android.graphics.Point;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.WindowManagerImpl;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.Predicate;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * UiDevice provides access to device wide states. Also provides methods to simulate
 * pressing hardware buttons such as DPad or the soft buttons such as Home and Menu.
 */
public class UiDevice {
    private static final String LOG_TAG = UiDevice.class.getSimpleName();

    private static final long DEFAULT_TIMEOUT_MILLIS = 10 * 1000;

    // store for registered UiWatchers
    private final HashMap<String, UiWatcher> mWatchers = new HashMap<String, UiWatcher>();
    private final List<String> mWatchersTriggers = new ArrayList<String>();

    // remember if we're executing in the context of a UiWatcher
    private boolean mInWatcherContext = false;

    // provides access the {@link QueryController} and {@link InteractionController}
    private final UiAutomatorBridge mUiAutomationBridge;

    // reference to self
    private static UiDevice mDevice;

    private UiDevice() {
        mUiAutomationBridge = new UiAutomatorBridge();
        mDevice = this;
    }

    boolean isInWatcherContext() {
        return mInWatcherContext;
    }

    /**
     * Provides access the {@link QueryController} and {@link InteractionController}
     * @return {@link UiAutomatorBridge}
     */
    UiAutomatorBridge getAutomatorBridge() {
        return mUiAutomationBridge;
    }
    /**
     * Allow both the direct creation of a UiDevice and retrieving a existing
     * instance of UiDevice. This helps tests and their libraries to have access
     * to UiDevice with necessitating having to always pass copies of UiDevice
     * instances around.
     * @return UiDevice instance
     */
    public static UiDevice getInstance() {
        if (mDevice == null) {
            mDevice = new UiDevice();
        }
        return mDevice;
    }

    /**
     * This method returns the text from the last UI traversal event received.
     * This is helpful in WebView when the test performs directional arrow presses to focus
     * on different elements inside the WebView. The accessibility fires events
     * with every text highlighted. One can read the contents of a WebView control this way
     * however slow slow and unreliable it is. When the view control used can return a
     * reference to is Document Object Model, it is recommended then to use the view's
     * DOM instead.
     * @return text of the last traversal event else an empty string
     */
    public String getLastTraversedText() {
        return mUiAutomationBridge.getQueryController().getLastTraversedText();
    }

    /**
     * Helper to clear the text saved from the last accessibility UI traversal event.
     * See {@link #getLastTraversedText()}.
     */
    public void clearLastTraversedText() {
        mUiAutomationBridge.getQueryController().clearLastTraversedText();
    }

    /**
     * Helper method to do a short press on MENU button
     * @return true if successful else false
     */
    public boolean pressMenu() {
        return pressKeyCode(KeyEvent.KEYCODE_MENU);
    }

    /**
     * Helper method to do a short press on BACK button
     * @return true if successful else false
     */
    public boolean pressBack() {
        return pressKeyCode(KeyEvent.KEYCODE_BACK);
    }

    /**
     * Helper method to do a short press on HOME button
     * @return true if successful else false
     */
    public boolean pressHome() {
        return pressKeyCode(KeyEvent.KEYCODE_HOME);
    }

    /**
     * Helper method to do a short press on SEARCH button
     * @return true if successful else false
     */
    public boolean pressSearch() {
        return pressKeyCode(KeyEvent.KEYCODE_SEARCH);
    }

    /**
     * Helper method to do a short press on DOWN button
     * @return true if successful else false
     */
    public boolean pressDPadCenter() {
        return pressKeyCode(KeyEvent.KEYCODE_DPAD_CENTER);
    }

    /**
     * Helper method to do a short press on DOWN button
     * @return true if successful else false
     */
    public boolean pressDPadDown() {
        return pressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN);
    }

    /**
     * Helper method to do a short press on UP button
     * @return true if successful else false
     */
    public boolean pressDPadUp() {
        return pressKeyCode(KeyEvent.KEYCODE_DPAD_UP);
    }

    /**
     * Helper method to do a short press on LEFT button
     * @return true if successful else false
     */
    public boolean pressDPadLeft() {
        return pressKeyCode(KeyEvent.KEYCODE_DPAD_LEFT);
    }

    /**
     * Helper method to do a short press on RIGTH button
     * @return true if successful else false
     */
    public boolean pressDPadRight() {
        return pressKeyCode(KeyEvent.KEYCODE_DPAD_RIGHT);
    }

    /**
     * Helper method to do a short press on DELETE
     * @return true if successful else false
     */
    public boolean pressDelete() {
        return pressKeyCode(KeyEvent.KEYCODE_DEL);
    }

    /**
     * Helper method to do a short press on ENTER
     * @return true if successful else false
     */
    public boolean pressEnter() {
        return pressKeyCode(KeyEvent.KEYCODE_ENTER);
    }

    /**
     * Helper method to do a short press using a key code. See {@link KeyEvent}
     * @return true if successful else false
     */
    public boolean pressKeyCode(int keyCode) {
        waitForIdle();
        return mUiAutomationBridge.getInteractionController().sendKey(keyCode, 0);
    }

    /**
     * Helper method to do a short press using a key code. See {@link KeyEvent}
     * @param keyCode See {@link KeyEvent}
     * @param metaState See {@link KeyEvent}
     * @return true if successful else false
     */
    public boolean pressKeyCode(int keyCode, int metaState) {
        waitForIdle();
        return mUiAutomationBridge.getInteractionController().sendKey(keyCode, metaState);
    }

    /**
     * Gets the width of the display, in pixels. The width and height details
     * are reported based on the current orientation of the display.
     * @return width in pixels or zero on failure
     */
    public int getDisplayWidth() {
        IWindowManager wm = IWindowManager.Stub.asInterface(
                ServiceManager.getService(Context.WINDOW_SERVICE));
        Point p = new Point();
        try {
            wm.getDisplaySize(p);
        } catch (RemoteException e) {
            return 0;
        }
        return p.x;
    }

    /**
     * Press recent apps soft key
     * @return true if successful
     * @throws RemoteException
     */
    public boolean pressRecentApps() throws RemoteException {
        waitForIdle();
        final IStatusBarService statusBar = IStatusBarService.Stub.asInterface(
                ServiceManager.getService(Context.STATUS_BAR_SERVICE));

        if (statusBar != null) {
            statusBar.toggleRecentApps();
            return true;
        }
        return false;
    }

    /**
     * Gets the height of the display, in pixels. The size is adjusted based
     * on the current orientation of the display.
     * @return height in pixels or zero on failure
     */
    public int getDisplayHeight() {
        IWindowManager wm = IWindowManager.Stub.asInterface(
                ServiceManager.getService(Context.WINDOW_SERVICE));
        Point p = new Point();
        try {
            wm.getDisplaySize(p);
        } catch (RemoteException e) {
            return 0;
        }
        return p.y;
    }

    /**
     * Perform a click at arbitrary coordinates specified by the user
     *
     * @param x coordinate
     * @param y coordinate
     * @return true if the click succeeded else false
     */
    public boolean click(int x, int y) {
        if (x >= getDisplayWidth() || y >= getDisplayHeight()) {
            return (false);
        }
        return getAutomatorBridge().getInteractionController().click(x, y);
    }

    /**
     * Performs a swipe from one coordinate to another using the number of steps
     * to determine smoothness and speed. Each step execution is throttled to 10ms
     * per step. So for a 100 steps, the swipe will take about 1 second to complete.
     *
     * @param startX
     * @param startY
     * @param endX
     * @param endY
     * @param steps is the number of move steps sent to the system
     * @return false if the operation fails or the coordinates are invalid
     */
    public boolean swipe(int startX, int startY, int endX, int endY, int steps) {
        return mUiAutomationBridge.getInteractionController()
                .scrollSwipe(startX, startY, endX, endY, steps);
    }

    /**
     * Performs a swipe between points in the Point array. Each step execution is throttled
     * to 10ms per step. So for a 100 steps, the swipe will take about 1 second to complete
     *
     * @param segments is Point array containing at least one Point object
     * @param segmentSteps steps to inject between two Points
     * @return true on success
     */
    public boolean swipe(Point[] segments, int segmentSteps) {
        return mUiAutomationBridge.getInteractionController().swipe(segments, segmentSteps);
    }

    public void waitForIdle() {
        waitForIdle(DEFAULT_TIMEOUT_MILLIS);
    }

    public void waitForIdle(long time) {
        mUiAutomationBridge.waitForIdle(time);
    }

    /**
     * Last activity to report accessibility events
     * @return String name of activity
     */
    public String getCurrentActivityName() {
        return mUiAutomationBridge.getQueryController().getCurrentActivityName();
    }

    /**
     * Last package to report accessibility events
     * @return String name of package
     */
    public String getCurrentPackageName() {
        return mUiAutomationBridge.getQueryController().getCurrentPackageName();
    }

    /**
     * Registers a condition watcher to be called by the automation library only when a
     * {@link UiObject} method call is in progress and is in retry waiting to match
     * its UI element. Only during these conditions the watchers are invoked to check if
     * there is something else unexpected on the screen that may be causing the match failure
     * and retries. Under normal conditions when UiObject methods are immediately matching
     * their UI element, watchers may never get to run. See {@link UiDevice#runWatchers()}
     *
     * @param name of watcher
     * @param watcher {@link UiWatcher}
     */
    public void registerWatcher(String name, UiWatcher watcher) {
        if (mInWatcherContext) {
            throw new IllegalStateException("Cannot register new watcher from within another");
        }
        mWatchers.put(name, watcher);
    }

    /**
     * Removes a previously registered {@link #registerWatcher(String, UiWatcher)}.
     *
     * @param name of watcher used when <code>registerWatcher</code> was called.
     * @throws UiAutomationException
     */
    public void removeWatcher(String name) {
        if (mInWatcherContext) {
            throw new IllegalStateException("Cannot remove a watcher from within another");
        }
        mWatchers.remove(name);
    }

    /**
     * See {@link #registerWatcher(String, UiWatcher)}. This forces all registered watchers
     * to run.
     */
    public void runWatchers() {
        if (mInWatcherContext) {
            return;
        }

        for (String watcherName : mWatchers.keySet()) {
            UiWatcher watcher = mWatchers.get(watcherName);
            if (watcher != null) {
                try {
                    mInWatcherContext = true;
                    if (watcher.checkForCondition()) {
                        setWatcherTriggered(watcherName);
                    }
                } catch (Exception e) {
                    Log.e(LOG_TAG, "Exceuting watcher: " + watcherName, e);
                } finally {
                    mInWatcherContext = false;
                }
            }
        }
    }

    /**
     * See {@link #registerWatcher(String, UiWatcher)}. If a watcher is run and
     * returns true from its implementation of {@link UiWatcher#checkForCondition()} then
     * it is considered triggered.
     */
    public void resetWatcherTriggers() {
        mWatchersTriggers.clear();
    }

    /**
     * See {@link #registerWatcher(String, UiWatcher)}. If a watcher is run and
     * returns true from its implementation of {@link UiWatcher#checkForCondition()} then
     * it is considered triggered. This method can be used to check if a specific UiWatcher
     * has been triggered during the test. This is helpful if a watcher is detecting errors
     * from ANR or crash dialogs and the test needs to know if a UiWatcher has been triggered.
     */
    public boolean hasWatcherTriggered(String watcherName) {
        return mWatchersTriggers.contains(watcherName);
    }

    /**
     * See {@link #registerWatcher(String, UiWatcher)} and {@link #hasWatcherTriggered(String)}
     */
    public boolean hasAnyWatcherTriggered() {
        return mWatchersTriggers.size() > 0;
    }

    private void setWatcherTriggered(String watcherName) {
        if (!hasWatcherTriggered(watcherName)) {
            mWatchersTriggers.add(watcherName);
        }
    }

    /**
     * Check if the device is in its natural orientation. This is determined by checking if the
     * orientation is at 0 or 180 degrees.
     * @return true if it is in natural orientation
     */
    public boolean isNaturalOrientation() {
        Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
        return display.getRotation() == Surface.ROTATION_0 ||
                display.getRotation() == Surface.ROTATION_180;
    }

    /**
     * Disables the sensors and freezes the device rotation at its
     * current rotation state.
     * @throws RemoteException
     */
    public void freezeRotation() throws RemoteException {
        getAutomatorBridge().getInteractionController().freezeRotation();
    }

    /**
     * Re-enables the sensors and un-freezes the device rotation allowing its contents
     * to rotate with the device physical rotation. Note that by un-freezing the rotation,
     * the screen contents may suddenly rotate depending on the current physical position
     * of the test device. During a test execution, it is best to keep the device frozen
     * in a specific orientation until the test case execution is completed.
     * @throws RemoteException
     */
    public void unfreezeRotation() throws RemoteException {
        getAutomatorBridge().getInteractionController().unfreezeRotation();
    }

    /**
     * Orients the device to the left and also freezes rotation in that
     * orientation by disabling the sensors. If you want to un-freeze the rotation
     * and re-enable the sensors see {@link #unfreezeRotation()}. Note that doing
     * so may cause the screen contents to get re-oriented depending on the current
     * physical position of the test device.
     * @throws RemoteException
     */
    public void setOrientationLeft() throws RemoteException {
        getAutomatorBridge().getInteractionController().setRotationLeft();
    }

    /**
     * Orients the device to the right and also freezes rotation in that
     * orientation by disabling the sensors. If you want to un-freeze the rotation
     * and re-enable the sensors see {@link #unfreezeRotation()}. Note that doing
     * so may cause the screen contents to get re-oriented depending on the current
     * physical position of the test device.
     * @throws RemoteException
     */
    public void setOrientationRight() throws RemoteException {
        getAutomatorBridge().getInteractionController().setRotationRight();
    }

    /**
     * Rotates right and also freezes rotation in that orientation by
     * disabling the sensors. If you want to un-freeze the rotation
     * and re-enable the sensors see {@link #unfreezeRotation()}. Note
     * that doing so may cause the screen contents to rotate
     * depending on the current physical position of the test device.
     * @throws RemoteException
     */
    public void setOrientationNatural() throws RemoteException {
        getAutomatorBridge().getInteractionController().setRotationNatural();
    }

    /**
     * This method simply presses the power button if the screen is OFF else
     * it does nothing if the screen is already ON. If the screen was OFF and
     * it just got turned ON, this method will insert a 500ms delay to allow
     * the device time to wake up and accept input.
     * @throws RemoteException
     */
    public void wakeUp() throws RemoteException {
        if(getAutomatorBridge().getInteractionController().wakeDevice()) {
            // sync delay to allow the window manager to start accepting input
            // after the device is awakened.
            SystemClock.sleep(500);
        }
    }

    /**
     * Checks the power manager if the screen is ON
     * @return true if the screen is ON else false
     * @throws RemoteException
     */
    public boolean isScreenOn() throws RemoteException {
        return getAutomatorBridge().getInteractionController().isScreenOn();
    }

    /**
     * This method simply presses the power button if the screen is ON else
     * it does nothing if the screen is already OFF.
     * @throws RemoteException
     */
    public void sleep() throws RemoteException {
        getAutomatorBridge().getInteractionController().sleepDevice();
    }

    /**
     * Helper method used for debugging to dump the current window's layout hierarchy.
     * The file root location is /data/local/tmp
     *
     * @param fileName
     */
    public void dumpWindowHierarchy(String fileName) {
        AccessibilityNodeInfo root =
                getAutomatorBridge().getQueryController().getAccessibilityRootNode();
        if(root != null) {
            AccessibilityNodeInfoDumper.dumpWindowToFile(
                    root, new File(new File(Environment.getDataDirectory(),
                            "local/tmp"), fileName));
        }
    }

    /**
     * Waits for a window content update event to occur
     *
     * if a package name for window is specified, but current window is not with the same package
     * name, the function will return immediately
     *
     * @param packageName the specified window package name; maybe <code>null</code>, and a window
     *                    update from any frontend window will end the wait
     * @param timeout the timeout for the wait
     *
     * @return true if a window update occured, false if timeout has reached or current window is
     * not the specified package name
     */
    public boolean waitForWindowUpdate(final String packageName, long timeout) {
        if (packageName != null) {
            if (!packageName.equals(getCurrentPackageName())) {
                return false;
            }
        }
        Runnable emptyRunnable = new Runnable() {
            @Override
            public void run() {
            }
        };
        Predicate<AccessibilityEvent> checkWindowUpdate = new Predicate<AccessibilityEvent>() {
            @Override
            public boolean apply(AccessibilityEvent t) {
                if (t.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
                    return packageName == null || packageName.equals(t.getPackageName());
                }
                return false;
            }
        };
        try {
            getAutomatorBridge().executeCommandAndWaitForAccessibilityEvent(
                    emptyRunnable, checkWindowUpdate, timeout);
        } catch (TimeoutException e) {
            return false;
        } catch (Exception e) {
            Log.e(LOG_TAG, "waitForWindowUpdate: general exception from bridge", e);
            return false;
        }
        return true;
    }
}
