/*
 * 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.widget.scroll;

import android.test.ActivityInstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.Suppress;
import android.view.KeyEvent;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;


public class ScrollViewButtonsAndLabelsTest
        extends ActivityInstrumentationTestCase<ScrollViewButtonsAndLabels> {

    private ScrollView mScrollView;
    private LinearLayout mLinearLayout;
    private int mScreenBottom;
    private int mScreenTop;

    public ScrollViewButtonsAndLabelsTest() {
        super("com.android.frameworks.coretests",
              ScrollViewButtonsAndLabels.class);
    }

    @Override
    public void setUp() throws Exception {
        super.setUp();
        mScrollView = getActivity().getScrollView();
        mLinearLayout = getActivity().getLinearLayout();

        int origin[] = {0, 0};
        mScrollView.getLocationOnScreen(origin);
        mScreenTop = origin[1];
        mScreenBottom = origin[1] + mScrollView.getHeight();
    }

    @MediumTest
    @Suppress // Failing.
    public void testPreconditions() {
        assertTrue("vertical fading edge width needs to be non-zero for this "
                + "test to be worth anything",
                mScrollView.getVerticalFadingEdgeLength() > 0);
    }

    // moving down to something off screen should move the element
    // onto the screen just above the vertical fading edge
    @LargeTest
    public void testArrowScrollDownOffScreenVerticalFadingEdge() {

        int offScreenIndex = findFirstButtonOffScreenTop2Bottom();
        Button firstButtonOffScreen = getActivity().getButton(offScreenIndex);

        getActivity().runOnUiThread(() -> getActivity().getButton(0).requestFocus());
        getInstrumentation().waitForIdleSync();

        for (int i = 0; i < offScreenIndex; i++) {
            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
        }
        getInstrumentation().waitForIdleSync();
        assertTrue(firstButtonOffScreen.hasFocus());

        assertTrue("the button we've moved to off screen must not be the last "
                + "button in the scroll view for this test to work (since we "
                + "are expecting the fading edge to be there).",
                offScreenIndex < getActivity().getNumButtons());

        // now we are at the first button off screen
        int buttonLoc[] = {0, 0};
        firstButtonOffScreen.getLocationOnScreen(buttonLoc);
        int buttonBottom = buttonLoc[1] + firstButtonOffScreen.getHeight();

        int verticalFadingEdgeLength = mScrollView
                .getVerticalFadingEdgeLength();
        assertEquals("bottom of button should be verticalFadingEdgeLength "
                + "above the bottom of the screen",
                buttonBottom, mScreenBottom - verticalFadingEdgeLength);
    }

    // there should be no offset for vertical fading edge
    // if the item is the last one on screen
    @LargeTest
    public void testArrowScrollDownToBottomElementOnScreen() {

        int numGroups = getActivity().getNumButtons();
        Button lastButton = getActivity().getButton(numGroups - 1);

        assertEquals("button needs to be at the very bottom of the layout for "
                + "this test to work",
                mLinearLayout.getHeight(), lastButton.getBottom());

        // move down to last button
        for (int i = 0; i < numGroups; i++) {
            sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
        }
        getInstrumentation().waitForIdleSync();
        assertTrue("last button should have focus", lastButton.hasFocus());

        int buttonLoc[] = {0, 0};
        lastButton.getLocationOnScreen(buttonLoc);
        int buttonBottom = buttonLoc[1] + lastButton.getHeight();
        assertEquals("button should be at very bottom of screen",
                mScreenBottom, buttonBottom);
    }

    @LargeTest
    public void testArrowScrollUpOffScreenVerticalFadingEdge() {
        // get to bottom button
        int numGroups = goToBottomButton();

        // go up to first off screen button
        int offScreenIndex = findFirstButtonOffScreenBottom2Top();
        Button offScreenButton = getActivity().getButton(offScreenIndex);
        int clicksToOffScreenIndex = numGroups - offScreenIndex - 1;
        for (int i = 0; i < clicksToOffScreenIndex; i++) {
            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
        }
        getInstrumentation().waitForIdleSync();
        assertTrue("we want to be at offScreenButton", offScreenButton.hasFocus());

        // top should take into account fading edge
        int buttonLoc[] = {0, 0};
        offScreenButton.getLocationOnScreen(buttonLoc);
        assertEquals("top should take into account fading edge",
            mScreenTop + mScrollView.getVerticalFadingEdgeLength(), buttonLoc[1]);
    }


    @LargeTest
    public void testArrowScrollUpToTopElementOnScreen() {
        // get to bottom button
        int numButtons = goToBottomButton();

        // go back to the top
        for (int i = 0; i < numButtons; i++) {
            sendKeys(KeyEvent.KEYCODE_DPAD_UP);
        }
        getInstrumentation().waitForIdleSync();

        Button topButton = getActivity().getButton(0);
        assertTrue("should be back at top button", topButton.hasFocus());


        int buttonLoc[] = {0, 0};
        topButton.getLocationOnScreen(buttonLoc);
        assertEquals("top of top button should be at top of screen; no need to take"
                + " into account vertical fading edge.",
                mScreenTop, buttonLoc[1]);
    }

    private int goToBottomButton() {
        int numButtons = getActivity().getNumButtons();
        Button lastButton = getActivity().getButton(numButtons - 1);

        for (int i = 0; i < numButtons; i++) {
          sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
        }
        getInstrumentation().waitForIdleSync();
        assertTrue("we want to be at the last button", lastButton.hasFocus());
        return numButtons;
    }

    // search from top to bottom for the first button off screen
    private int findFirstButtonOffScreenTop2Bottom() {
        int origin[] = {0, 0};
        mScrollView.getLocationOnScreen(origin);
        int screenHeight = mScrollView.getHeight();

        for (int i = 0; i < getActivity().getNumButtons(); i++) {

            int buttonLoc[] = {0, 0};
            Button button = getActivity().getButton(i);
            button.getLocationOnScreen(buttonLoc);

            if (buttonLoc[1] - origin[1] > screenHeight) {
                return i;
            }
        }
        fail("couldn't find first button off screen");
        return -1; // this won't execute, but the compiler needs it
    }

    private int findFirstButtonOffScreenBottom2Top() {
        int origin[] = {0, 0};
        mScrollView.getLocationOnScreen(origin);

        for (int i = getActivity().getNumButtons() - 1; i >= 0; i--) {

            int buttonLoc[] = {0, 0};
            Button button = getActivity().getButton(i);
            button.getLocationOnScreen(buttonLoc);

            if (buttonLoc[1] < 0) {
                return i;
            }
        }
        fail("couldn't find first button off screen");
        return -1; // this won't execute, but the compiler needs it
    }

}
