/*
 * 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.graphics.Rect;
import android.util.Log;
import android.view.accessibility.AccessibilityNodeInfo;

/**
 * UiScrollable is a {@link UiCollection} and provides support for searching for items in a
 * scrollable UI elements. Used with horizontally or vertically scrollable UI.
 * @since API Level 16
 */
public class UiScrollable extends UiCollection {
    private static final String LOG_TAG = UiScrollable.class.getSimpleName();

    // More steps slows the swipe and prevents contents from being flung too far
    private static final int SCROLL_STEPS = 55;

    private static final int FLING_STEPS = 5;

    // Restrict a swipe's starting and ending points inside a 10% margin of the target
    private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;

    // Limits the number of swipes/scrolls performed during a search
    private static int mMaxSearchSwipes = 30;

    // Used in ScrollForward() and ScrollBackward() to determine swipe direction
    private boolean mIsVerticalList = true;

    private double mSwipeDeadZonePercentage = DEFAULT_SWIPE_DEADZONE_PCT;

    /**
     * UiScrollable is a {@link UiCollection} and as such requires a {@link UiSelector} to
     * identify the container UI element of the scrollable collection. Further operations on
     * the items in the container will require specifying UiSelector as an item selector.
     *
     * @param container a {@link UiSelector} selector
     * @since API Level 16
     */
    public UiScrollable(UiSelector container) {
        // wrap the container selector with container so that QueryController can handle
        // this type of enumeration search accordingly
        super(container);
    }

    /**
     * Set the direction of swipes when performing scroll search
     * @return reference to itself
     * @since API Level 16
     */
    public UiScrollable setAsVerticalList() {
        Tracer.trace();
        mIsVerticalList = true;
        return this;
    }

    /**
     * Set the direction of swipes when performing scroll search
     * @return reference to itself
     * @since API Level 16
     */
    public UiScrollable setAsHorizontalList() {
        Tracer.trace();
        mIsVerticalList = false;
        return this;
    }

    /**
     * Used privately when performing swipe searches to decide if an element has become
     * visible or not.
     *
     * @param selector
     * @return true if found else false
     * @since API Level 16
     */
    protected boolean exists(UiSelector selector) {
        if(getQueryController().findAccessibilityNodeInfo(selector) != null) {
            return true;
        }
        return false;
    }

    /**
     * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector}
     * container. It looks for any child matching the <code>childPattern</code> argument within its
     * hierarchy with a matching content-description text. The returned UiObject will represent the
     * UI element matching the <code>childPattern</code> and not the sub element that matched the
     * content description.</p>
     * By default this operation will perform scroll search while attempting to find the UI element
     * See {@link #getChildByDescription(UiSelector, String, boolean)}
     *
     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
     * @param text String of the identifying child contents of of the <code>childPattern</code>
     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
     * @throws UiObjectNotFoundException
     * @since API Level 16
     */
    @Override
    public UiObject getChildByDescription(UiSelector childPattern, String text)
            throws UiObjectNotFoundException {
        Tracer.trace(childPattern, text);
        return getChildByDescription(childPattern, text, true);
    }

    /**
     * See {@link #getChildByDescription(UiSelector, String)}
     *
     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
     * @param text String may be a partial match for the content-description of a child element.
     * @param allowScrollSearch set to true if scrolling is allowed
     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
     * @throws UiObjectNotFoundException
     * @since API Level 16
     */
    public UiObject getChildByDescription(UiSelector childPattern, String text,
            boolean allowScrollSearch) throws UiObjectNotFoundException {
        Tracer.trace(childPattern, text, allowScrollSearch);
        if (text != null) {
            if (allowScrollSearch) {
                scrollIntoView(new UiSelector().descriptionContains(text));
            }
            return super.getChildByDescription(childPattern, text);
        }
        throw new UiObjectNotFoundException("for description= \"" + text + "\"");
    }

    /**
     * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector}
     * selector. It looks for any child matching the <code>childPattern</code> argument and
     * return the <code>instance</code> specified. The operation is performed only on the visible
     * items and no scrolling is performed in this case.
     *
     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
     * @param instance int the desired matched instance of this <code>childPattern</code>
     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
     * @since API Level 16
     */
    @Override
    public UiObject getChildByInstance(UiSelector childPattern, int instance)
            throws UiObjectNotFoundException {
        Tracer.trace(childPattern, instance);
        UiSelector patternSelector = UiSelector.patternBuilder(getSelector(),
                UiSelector.patternBuilder(childPattern).instance(instance));
        return new UiObject(patternSelector);
    }

    /**
     * Searches for child UI element within the constraints of this UiScrollable {@link UiSelector}
     * container. It looks for any child matching the <code>childPattern</code> argument that has
     * a sub UI element anywhere within its sub hierarchy that has text attribute
     * <code>text</code>. The returned UiObject will point at the <code>childPattern</code>
     * instance that matched the search and not at the text matched sub element</p>
     * By default this operation will perform scroll search while attempting to find the UI
     * element.
     * See {@link #getChildByText(UiSelector, String, boolean)}
     *
     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
     * @param text String of the identifying child contents of of the <code>childPattern</code>
     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
     * @throws UiObjectNotFoundException
     * @since API Level 16
     */
    @Override
    public UiObject getChildByText(UiSelector childPattern, String text)
            throws UiObjectNotFoundException {
        Tracer.trace(childPattern, text);
        return getChildByText(childPattern, text, true);
    }

    /**
     * See {@link #getChildByText(UiSelector, String)}
     *
     * @param childPattern {@link UiSelector} selector of the child pattern to match and return
     * @param text String of the identifying child contents of of the <code>childPattern</code>
     * @param allowScrollSearch set to true if scrolling is allowed
     * @return {@link UiObject} pointing at and instance of <code>childPattern</code>
     * @throws UiObjectNotFoundException
     * @since API Level 16
     */
    public UiObject getChildByText(UiSelector childPattern, String text, boolean allowScrollSearch)
            throws UiObjectNotFoundException {
        Tracer.trace(childPattern, text, allowScrollSearch);
        if (text != null) {
            if (allowScrollSearch) {
                scrollIntoView(new UiSelector().text(text));
            }
            return super.getChildByText(childPattern, text);
        }
        throw new UiObjectNotFoundException("for text= \"" + text + "\"");
    }

    /**
     * Performs a swipe Up on the UI element until the requested content-description
     * is visible or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)}
     *
     * @param text to look for anywhere within the contents of this scrollable.
     * @return true if item us found else false
     * @since API Level 16
     */
    public boolean scrollDescriptionIntoView(String text) throws UiObjectNotFoundException {
        Tracer.trace(text);
        return scrollIntoView(new UiSelector().description(text));
    }

    /**
     * Perform a scroll search for a UI element matching the {@link UiSelector} selector argument.
     * See {@link #scrollDescriptionIntoView(String)} and {@link #scrollTextIntoView(String)}.
     *
     * @param obj {@link UiObject}
     * @return true if the item was found and now is in view else false
     * @since API Level 16
     */
    public boolean scrollIntoView(UiObject obj) throws UiObjectNotFoundException {
        Tracer.trace(obj.getSelector());
        return scrollIntoView(obj.getSelector());
    }

    /**
     * Perform a scroll search for a UI element matching the {@link UiSelector} selector argument.
     * See {@link #scrollDescriptionIntoView(String)} and {@link #scrollTextIntoView(String)}.
     *
     * @param selector {@link UiSelector} selector
     * @return true if the item was found and now is in view else false
     * @since API Level 16
     */
    public boolean scrollIntoView(UiSelector selector) throws UiObjectNotFoundException {
        Tracer.trace(selector);
        // if we happen to be on top of the text we want then return here
        if (exists(getSelector().childSelector(selector))) {
            return (true);
        } else {
            // we will need to reset the search from the beginning to start search
            scrollToBeginning(mMaxSearchSwipes);
            if (exists(getSelector().childSelector(selector))) {
                return (true);
            }
            for (int x = 0; x < mMaxSearchSwipes; x++) {
                if(!scrollForward()) {
                    return false;
                }

                if(exists(getSelector().childSelector(selector))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Performs a swipe up on the UI element until the requested text is visible
     * or until swipe attempts have been exhausted. See {@link #setMaxSearchSwipes(int)}
     *
     * @param text to look for
     * @return true if item us found else false
     * @since API Level 16
     */
    public boolean scrollTextIntoView(String text) throws UiObjectNotFoundException {
        Tracer.trace(text);
        return scrollIntoView(new UiSelector().text(text));
    }

    /**
     * {@link #getChildByDescription(UiSelector, String)} and
     * {@link #getChildByText(UiSelector, String)} use an arguments that specifies if scrolling is
     * allowed while searching for the UI element.  The number of scrolls allowed to perform a
     * search can be modified by this method.  The current value can be read by calling
     * {@link #getMaxSearchSwipes()}
     *
     * @param swipes is the number of search swipes until abort
     * @return reference to itself
     * @since API Level 16
     */
    public UiScrollable setMaxSearchSwipes(int swipes) {
        Tracer.trace(swipes);
        mMaxSearchSwipes = swipes;
        return this;
    }

    /**
     * {@link #getChildByDescription(UiSelector, String)} and
     * {@link #getChildByText(UiSelector, String)} use an arguments that specifies if scrolling is
     * allowed while searching for the UI element.  The number of scrolls currently allowed to
     * perform a search can be read by this method.
     * See {@link #setMaxSearchSwipes(int)}
     *
     * @return max value of the number of swipes currently allowed during a scroll search
     * @since API Level 16
     */
    public int getMaxSearchSwipes() {
        Tracer.trace();
        return mMaxSearchSwipes;
    }

    /**
     * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a fling
     *
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean flingForward() throws UiObjectNotFoundException {
        Tracer.trace();
        return scrollForward(FLING_STEPS);
    }

    /**
     * A convenience version of {@link UiScrollable#scrollForward(int)}, performs a regular scroll
     *
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean scrollForward() throws UiObjectNotFoundException {
        Tracer.trace();
        return scrollForward(SCROLL_STEPS);
    }

    /**
     * Perform a scroll forward. If this list is set to vertical (see {@link #setAsVerticalList()}
     * default) then the swipes will be executed from the bottom to top. If this list is set
     * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from
     * the right to left. Caution is required on devices configured with right to left languages
     * like Arabic and Hebrew.
     *
     * @param steps use steps to control the speed, so that it may be a scroll, or fling
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean scrollForward(int steps) throws UiObjectNotFoundException {
        Tracer.trace(steps);
        Log.d(LOG_TAG, "scrollForward() on selector = " + getSelector());
        AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
        if(node == null) {
            throw new UiObjectNotFoundException(getSelector().toString());
        }
        Rect rect = new Rect();
        node.getBoundsInScreen(rect);

        int downX = 0;
        int downY = 0;
        int upX = 0;
        int upY = 0;

        // scrolling is by default assumed vertically unless the object is explicitly
        // set otherwise by setAsHorizontalContainer()
        if(mIsVerticalList) {
            int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage());
            // scroll vertically: swipe down -> up
            downX = rect.centerX();
            downY = rect.bottom - swipeAreaAdjust;
            upX = rect.centerX();
            upY = rect.top + swipeAreaAdjust;
        } else {
            int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage());
            // scroll horizontally: swipe right -> left
            // TODO: Assuming device is not in right to left language
            downX = rect.right - swipeAreaAdjust;
            downY = rect.centerY();
            upX = rect.left + swipeAreaAdjust;
            upY = rect.centerY();
        }
        return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps);
    }

    /**
     * See {@link UiScrollable#scrollBackward(int)}
     *
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean flingBackward() throws UiObjectNotFoundException {
        Tracer.trace();
        return scrollBackward(FLING_STEPS);
    }

    /**
     * See {@link UiScrollable#scrollBackward(int)}
     *
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean scrollBackward() throws UiObjectNotFoundException {
        Tracer.trace();
        return scrollBackward(SCROLL_STEPS);
    }

    /**
     * Perform a scroll backward. If this list is set to vertical (see {@link #setAsVerticalList()}
     * default) then the swipes will be executed from the top to bottom. If this list is set
     * to horizontal (see {@link #setAsHorizontalList()}) then the swipes will be executed from
     * the left to right. Caution is required on devices configured with right to left languages
     * like Arabic and Hebrew.
     *
     * @param steps use steps to control the speed, so that it may be a scroll, or fling
     * @return true if scrolled and false if can't scroll anymore
     * @since API Level 16
     */
    public boolean scrollBackward(int steps) throws UiObjectNotFoundException {
        Tracer.trace(steps);
        Log.d(LOG_TAG, "scrollBackward() on selector = " + getSelector());
        AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT);
        if (node == null) {
            throw new UiObjectNotFoundException(getSelector().toString());
        }
        Rect rect = new Rect();
        node.getBoundsInScreen(rect);

        int downX = 0;
        int downY = 0;
        int upX = 0;
        int upY = 0;

        // scrolling is by default assumed vertically unless the object is explicitly
        // set otherwise by setAsHorizontalContainer()
        if(mIsVerticalList) {
            int swipeAreaAdjust = (int)(rect.height() * getSwipeDeadZonePercentage());
            Log.d(LOG_TAG, "scrollToBegining() using vertical scroll");
            // scroll vertically: swipe up -> down
            downX = rect.centerX();
            downY = rect.top + swipeAreaAdjust;
            upX = rect.centerX();
            upY = rect.bottom - swipeAreaAdjust;
        } else {
            int swipeAreaAdjust = (int)(rect.width() * getSwipeDeadZonePercentage());
            Log.d(LOG_TAG, "scrollToBegining() using hotizontal scroll");
            // scroll horizontally: swipe left -> right
            // TODO: Assuming device is not in right to left language
            downX = rect.left + swipeAreaAdjust;
            downY = rect.centerY();
            upX = rect.right - swipeAreaAdjust;
            upY = rect.centerY();
        }
        return getInteractionController().scrollSwipe(downX, downY, upX, upY, steps);
    }

    /**
     * Scrolls to the beginning of a scrollable UI element. The beginning could be the top most
     * in case of vertical lists or the left most in case of horizontal lists. Caution is required
     * on devices configured with right to left languages like Arabic and Hebrew.
     *
     * @param steps use steps to control the speed, so that it may be a scroll, or fling
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean scrollToBeginning(int maxSwipes, int steps) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes, steps);
        Log.d(LOG_TAG, "scrollToBeginning() on selector = " + getSelector());
        // protect against potential hanging and return after preset attempts
        for(int x = 0; x < maxSwipes; x++) {
            if(!scrollBackward(steps)) {
                break;
            }
        }
        return true;
    }

    /**
     * See {@link UiScrollable#scrollToBeginning(int, int)}
     *
     * @param maxSwipes
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean scrollToBeginning(int maxSwipes) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes);
        return scrollToBeginning(maxSwipes, SCROLL_STEPS);
    }

    /**
     * See {@link UiScrollable#scrollToBeginning(int, int)}
     *
     * @param maxSwipes
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean flingToBeginning(int maxSwipes) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes);
        return scrollToBeginning(maxSwipes, FLING_STEPS);
    }

    /**
     * Scrolls to the end of a scrollable UI element. The end could be the bottom most
     * in case of vertical controls or the right most for horizontal controls. Caution
     * is required on devices configured with right to left languages like Arabic and Hebrew.
     *
     * @param steps use steps to control the speed, so that it may be a scroll, or fling
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean scrollToEnd(int maxSwipes, int steps) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes, steps);
        // protect against potential hanging and return after preset attempts
        for(int x = 0; x < maxSwipes; x++) {
            if(!scrollForward(steps)) {
                break;
            }
        }
        return true;
    }

    /**
     * See {@link UiScrollable#scrollToEnd(int, int)}
     *
     * @param maxSwipes
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean scrollToEnd(int maxSwipes) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes);
        return scrollToEnd(maxSwipes, SCROLL_STEPS);
    }

    /**
     * See {@link UiScrollable#scrollToEnd(int, int)}
     *
     * @param maxSwipes
     * @return true on scrolled else false
     * @since API Level 16
     */
    public boolean flingToEnd(int maxSwipes) throws UiObjectNotFoundException {
        Tracer.trace(maxSwipes);
        return scrollToEnd(maxSwipes, FLING_STEPS);
    }

    /**
     * Returns the percentage of a widget's size that's considered as no touch zone when swiping
     *
     * Dead zones are set as percentage of a widget's total width or height where
     * swipe start point cannot start or swipe end point cannot end. It is like a margin
     * around the actual dimensions of the widget. Swipes will always be start and
     * end inside this margin.
     *
     * This is important when the widget being swiped may not respond to the swipe if
     * started at a point too near to the edge. The default is 10% from either edge.
     *
     * @return a value between 0 and 1
     * @since API Level 16
     */
    public double getSwipeDeadZonePercentage() {
        Tracer.trace();
        return mSwipeDeadZonePercentage;
    }

    /**
     * Sets the percentage of a widget's size that's considered as no touch zone when swiping
     *
     * Dead zones are set as percentage of a widget's total width or height where
     * swipe start point cannot start or swipe end point cannot end. It is like a margin
     * around the actual dimensions of the widget. Swipes will always start and
     * end inside this margin.
     *
     * This is important when the widget being swiped may not respond to the swipe if
     * started at a point too near to the edge. The default is 10% from either edge
     *
     * @param swipeDeadZonePercentage is a value between 0 and 1
     * @return reference to itself
     * @since API Level 16
     */
    public UiScrollable setSwipeDeadZonePercentage(double swipeDeadZonePercentage) {
        Tracer.trace(swipeDeadZonePercentage);
        mSwipeDeadZonePercentage = swipeDeadZonePercentage;
        return this;
    }
}
