/*
 * Copyright (C) 2008 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.text.method.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.app.Activity;
import android.app.Instrumentation;
import android.os.SystemClock;
import android.text.Layout;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.method.Touch;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@MediumTest
@RunWith(AndroidJUnit4.class)
public class TouchTest {
    private static final String LONG_TEXT = "Scrolls the specified widget to the specified " +
            "coordinates, except constrains the X scrolling position to the horizontal regions " +
            "of the text that will be visible after scrolling to the specified Y position." +
            "This is the description of the test." +
            "Scrolls the specified widget to the specified " +
            "coordinates, except constrains the X scrolling position to the horizontal regions " +
            "of the text that will be visible after scrolling to the specified Y position." +
            "This is the description of the test.";

    private Instrumentation mInstrumentation;
    private Activity mActivity;
    private boolean mReturnFromTouchEvent;
    private TextView mTextView;

    @Rule
    public ActivityTestRule<CtsActivity> mActivityRule = new ActivityTestRule<>(CtsActivity.class);

    @UiThreadTest
    @Before
    public void setup() {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mTextView = new TextViewNoIme(mActivity);
        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
    }

    @Test
    public void testScrollTo() throws Throwable {
        mActivityRule.runOnUiThread(() -> {
            final float pixelPerSp =
                mActivity.getResources().getDisplayMetrics().scaledDensity;
            // Explicitly set the width so that |LONG_TEXT| causes horizontal scroll.
            mActivity.setContentView(mTextView, new ViewGroup.LayoutParams(
                (int)(100 * pixelPerSp), ViewGroup.LayoutParams.MATCH_PARENT));
            mTextView.setSingleLine(true);
            mTextView.setLines(2);
        });
        mInstrumentation.waitForIdleSync();
        TextPaint paint = mTextView.getPaint();
        final Layout layout = mTextView.getLayout();

        mActivityRule.runOnUiThread(() -> mTextView.setText(LONG_TEXT));
        mInstrumentation.waitForIdleSync();

        // get the total length of string
        final int width = getTextWidth(LONG_TEXT, paint);

        mActivityRule.runOnUiThread(
                () -> Touch.scrollTo(mTextView, layout, width - mTextView.getWidth() - 1, 0));
        mInstrumentation.waitForIdleSync();
        assertEquals(width - mTextView.getWidth() - 1, mTextView.getScrollX());
        assertEquals(0, mTextView.getScrollY());

        // the X to which scroll is greater than the total length of string.
        mActivityRule.runOnUiThread(() -> Touch.scrollTo(mTextView, layout, width + 100, 5));
        mInstrumentation.waitForIdleSync();
        assertEquals(width - mTextView.getWidth(), mTextView.getScrollX(), 1.0f);
        assertEquals(5, mTextView.getScrollY());

        mActivityRule.runOnUiThread(() -> Touch.scrollTo(mTextView, layout, width - 10, 5));
        mInstrumentation.waitForIdleSync();
        assertEquals(width - mTextView.getWidth(), mTextView.getScrollX(), 1.0f);
        assertEquals(5, mTextView.getScrollY());
    }

    @Test
    public void testOnTouchEvent() throws Throwable {
        // Create a string that is wider than the screen.
        DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
        int screenWidth = metrics.widthPixels;
        TextPaint paint = mTextView.getPaint();
        String text = LONG_TEXT;
        int textWidth = Math.round(paint.measureText(text));
        while (textWidth < screenWidth) {
            text += LONG_TEXT;
            textWidth = Math.round(paint.measureText(text));
        }

        // Drag the difference between the text width and the screen width.
        int dragAmount = Math.min(screenWidth, textWidth - screenWidth);
        assertTrue(dragAmount > 0);
        final String finalText = text;
        final SpannableString spannable = new SpannableString(finalText);
        mActivityRule.runOnUiThread(() -> {
            mActivity.setContentView(mTextView);
            mTextView.setSingleLine(true);
            mTextView.setText(finalText);
        });
        mInstrumentation.waitForIdleSync();

        long downTime = SystemClock.uptimeMillis();
        long eventTime = SystemClock.uptimeMillis();
        final MotionEvent event1 = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_DOWN, dragAmount, 0, 0);
        final MotionEvent event2 = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_MOVE, 0, 0, 0);
        final MotionEvent event3 = MotionEvent.obtain(downTime, eventTime,
                MotionEvent.ACTION_UP, 0, 0, 0);
        assertEquals(0, mTextView.getScrollX());
        assertEquals(0, mTextView.getScrollY());
        mReturnFromTouchEvent = false;
        mActivityRule.runOnUiThread(
                () -> mReturnFromTouchEvent = Touch.onTouchEvent(mTextView, spannable, event1));
        mInstrumentation.waitForIdleSync();
        assertTrue(mReturnFromTouchEvent);
        // TextView has not been scrolled.
        assertEquals(0, mTextView.getScrollX());
        assertEquals(0, mTextView.getScrollY());
        assertEquals(0, Touch.getInitialScrollX(mTextView, spannable));
        assertEquals(0, Touch.getInitialScrollY(mTextView, spannable));

        mReturnFromTouchEvent = false;
        mActivityRule.runOnUiThread(
                () -> mReturnFromTouchEvent = Touch.onTouchEvent(mTextView, spannable, event2));
        mInstrumentation.waitForIdleSync();
        assertTrue(mReturnFromTouchEvent);
        // TextView has been scrolled.
        assertEquals(dragAmount, mTextView.getScrollX());
        assertEquals(0, mTextView.getScrollY());
        assertEquals(0, Touch.getInitialScrollX(mTextView, spannable));
        assertEquals(0, Touch.getInitialScrollY(mTextView, spannable));

        mReturnFromTouchEvent = false;
        mActivityRule.runOnUiThread(
                () -> mReturnFromTouchEvent = Touch.onTouchEvent(mTextView, spannable, event3));
        mInstrumentation.waitForIdleSync();
        assertTrue(mReturnFromTouchEvent);
        // TextView has not been scrolled.
        assertEquals(dragAmount, mTextView.getScrollX());
        assertEquals(0, mTextView.getScrollY());
        assertEquals(-1, Touch.getInitialScrollX(mTextView, spannable));
        assertEquals(-1, Touch.getInitialScrollY(mTextView, spannable));
    }

    private int getTextWidth(String str, TextPaint paint) {
        float totalWidth = 0f;
        float[] widths = new float[str.length()];
        paint.getTextWidths(str, widths);
        for (float f : widths) {
            totalWidth += f;
        }
        return (int) totalWidth;
    }
}
