/*
 * 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 android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.TextView.BufferType;

/**
 * Test {@link LinkMovementMethod}. The class is an implementation of interface
 * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in
 * {@link android.widget.cts.TextViewTest} and this test case is only focused on the
 * implementation of the methods.
 *
 * @see android.widget.cts.TextViewTest
 */
public class LinkMovementMethodTest extends
        ActivityInstrumentationTestCase2<CtsActivity> {
    private static final String CONTENT = "clickable\nunclickable\nclickable";

    private LinkMovementMethod mMethod;

    private TextView mView;

    private Spannable mSpannable;

    private MockClickableSpan mClickable0;

    private MockClickableSpan mClickable1;

    public LinkMovementMethodTest() {
        super("com.android.cts.text", CtsActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mMethod = new LinkMovementMethod();

        // Set the content view with a text view which contains 3 lines,
        mView = new TextView(getActivity());
        mView.setText(CONTENT, BufferType.SPANNABLE);
        getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                getActivity().setContentView(mView);
            }
        });
        getInstrumentation().waitForIdleSync();

        mSpannable = (Spannable) mView.getText();
        // make first line clickable
        mClickable0 = markClickable(0, CONTENT.indexOf('\n'));
        // make last line clickable
        mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length());
    }

    public void testConstructor() {
        new LinkMovementMethod();
    }

    public void testGetInstance() {
        MovementMethod method0 = LinkMovementMethod.getInstance();
        assertTrue(method0 instanceof LinkMovementMethod);

        MovementMethod method1 = LinkMovementMethod.getInstance();
        assertNotNull(method1);
        assertSame(method0, method1);
    }

    public void testOnTakeFocus() {
        LinkMovementMethod method = new LinkMovementMethod();
        Spannable spannable = new SpannableString("test sequence");
        Selection.setSelection(spannable, 0, spannable.length());

        assertSelection(spannable, 0, spannable.length());
        assertTrue("Expected at least 2 spans", 2 <= spannable.getSpans(0, spannable.length(), Object.class).length);
        method.onTakeFocus(null, spannable, View.FOCUS_UP);
        assertSelection(spannable, -1);
        assertEquals(1, spannable.getSpans(0, spannable.length(), Object.class).length);
        Object span = spannable.getSpans(0, spannable.length(), Object.class)[0];
        assertEquals(0, spannable.getSpanStart(span));
        assertEquals(0, spannable.getSpanEnd(span));
        assertEquals(Spanned.SPAN_POINT_POINT, spannable.getSpanFlags(span));

        // focus forwards
        Selection.setSelection(spannable, 0, spannable.length());
        assertSelection(spannable, 0, spannable.length());
        assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length);
        method.onTakeFocus(null, spannable, View.FOCUS_RIGHT);
        assertSelection(spannable, -1);
        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);

        // force adding span while focus backward
        method.onTakeFocus(null, spannable, View.FOCUS_UP);
        // param direction is unknown(0)
        Selection.setSelection(spannable, 0, spannable.length());
        assertSelection(spannable, 0, spannable.length());
        assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length);
        method.onTakeFocus(null, spannable, 0);
        assertSelection(spannable, -1);
        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);

        // null parameters
        try {
            method.onTakeFocus(new TextView(getActivity()), null, View.FOCUS_RIGHT);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testOnKeyDown() {
        // no selection
        assertSelection(mSpannable, -1);
        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
        assertFalse(mClickable0.hasCalledOnClick());
        assertFalse(mClickable1.hasCalledOnClick());

        // select clickable0
        Selection.setSelection(mSpannable, mSpannable.getSpanStart(mClickable0),
                mSpannable.getSpanEnd(mClickable0));
        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
        assertTrue(mClickable0.hasCalledOnClick());
        assertFalse(mClickable1.hasCalledOnClick());

        // select unclickable
        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
                mSpannable.getSpanStart(mClickable1));
        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_ENTER,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
        assertFalse(mClickable0.hasCalledOnClick());
        assertFalse(mClickable1.hasCalledOnClick());

        // select all clickables(more than one)
        Selection.selectAll(mSpannable);
        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
        assertFalse(mClickable0.hasCalledOnClick());
        assertFalse(mClickable1.hasCalledOnClick());

        // part of selection is clickable
        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
                mSpannable.getSpanEnd(mClickable1));
        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER)));
        assertFalse(mClickable0.hasCalledOnClick());
        assertTrue(mClickable1.hasCalledOnClick());

        // selection contains only clickable1 and repeat count of the event is not 0
        Selection.setSelection(mSpannable, mSpannable.getSpanEnd(mClickable0),
        mSpannable.getSpanEnd(mClickable1));
        long now = SystemClock.uptimeMillis();
        KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN,
                KeyEvent.KEYCODE_DPAD_CENTER, 1);

        mClickable0.reset();
        mClickable1.reset();
        assertFalse(mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, event));
        assertFalse(mClickable0.hasCalledOnClick());
        assertFalse(mClickable1.hasCalledOnClick());

        // null parameters
        try {
            mMethod.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER,
                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            mMethod.onKeyDown(mView, null, KeyEvent.KEYCODE_DPAD_CENTER,
                    new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER));
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            mMethod.onKeyDown(mView, mSpannable, KeyEvent.KEYCODE_DPAD_CENTER, null);
            fail("The method did not throw NullPointerException when param keyEvent is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    public void testOnKeyUp() {
        LinkMovementMethod method = new LinkMovementMethod();
        // always returns false
        assertFalse(method.onKeyUp(null, null, 0, null));
        assertFalse(method.onKeyUp(new TextView(getActivity()), null, 0, null));
        assertFalse(method.onKeyUp(null, new SpannableString("blahblah"), 0, null));
        assertFalse(method.onKeyUp(null, null, KeyEvent.KEYCODE_0,
                new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0)));
    }

    @UiThreadTest
    public void testOnTouchEvent() {
        assertSelection(mSpannable, -1);

        // press on first line (Clickable)
        assertTrue(pressOnLine(0));
        assertSelectClickableLeftToRight(mSpannable, mClickable0);

        // release on first line
        assertFalse(mClickable0.hasCalledOnClick());
        assertTrue(releaseOnLine(0));
        assertTrue(mClickable0.hasCalledOnClick());

        // press on second line (unclickable)
        assertSelectClickableLeftToRight(mSpannable, mClickable0);
        // just clear selection
        pressOnLine(1);
        assertSelection(mSpannable, -1);

        // press on last line  (Clickable)
        assertTrue(pressOnLine(2));
        assertSelectClickableLeftToRight(mSpannable, mClickable1);

        // release on last line
        assertFalse(mClickable1.hasCalledOnClick());
        assertTrue(releaseOnLine(2));
        assertTrue(mClickable1.hasCalledOnClick());

        // release on second line (unclickable)
        assertSelectClickableLeftToRight(mSpannable, mClickable1);
        // just clear selection
        releaseOnLine(1);
        assertSelection(mSpannable, -1);

        // null parameters
        long now = SystemClock.uptimeMillis();
        int y = (mView.getLayout().getLineTop(1) + mView.getLayout().getLineBottom(1)) / 2;
        try {
            mMethod.onTouchEvent(null, mSpannable,
                    MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            mMethod.onTouchEvent(mView, null,
                    MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 5, y, 0));
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            mMethod.onTouchEvent(mView, mSpannable, null);
            fail("The method did not throw NullPointerException when param keyEvent is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testUp() {
        final MyLinkMovementMethod method = new MyLinkMovementMethod();
        assertSelection(mSpannable, -1);

        assertTrue(method.up(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable1);

        assertTrue(method.up(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable0);

        assertFalse(method.up(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable0);

        // null parameters
        try {
            method.up(null, mSpannable);
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            method.up(mView, null);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testDown() {
        final MyLinkMovementMethod method = new MyLinkMovementMethod();
        assertSelection(mSpannable, -1);

        assertTrue(method.down(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable0);

        assertTrue(method.down(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable1);

        assertFalse(method.down(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable1);

        // null parameters
        try {
            method.down(null, mSpannable);
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            method.down(mView, null);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testLeft() {
        final MyLinkMovementMethod method = new MyLinkMovementMethod();
        assertSelection(mSpannable, -1);

        assertTrue(method.left(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable1);

        assertTrue(method.left(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable0);

        assertFalse(method.left(mView, mSpannable));
        assertSelectClickableRightToLeft(mSpannable, mClickable0);

        // null parameters
        try {
            method.left(null, mSpannable);
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            method.left(mView, null);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testRight() {
        final MyLinkMovementMethod method = new MyLinkMovementMethod();
        assertSelection(mSpannable, -1);

        assertTrue(method.right(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable0);

        assertTrue(method.right(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable1);

        assertFalse(method.right(mView, mSpannable));
        assertSelectClickableLeftToRight(mSpannable, mClickable1);

        // null parameters
        try {
            method.right(null, mSpannable);
            fail("The method did not throw NullPointerException when param view is null.");
        } catch (NullPointerException e) {
            // expected
        }

        try {
            method.right(mView, null);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    @UiThreadTest
    public void testMoveAroundUnclickable() {
        final MyLinkMovementMethod method = new MyLinkMovementMethod();
        mSpannable.removeSpan(mClickable0);
        mSpannable.removeSpan(mClickable1);
        assertSelection(mSpannable, -1);

        assertFalse(method.up(mView, mSpannable));
        assertSelection(mSpannable, -1);

        assertFalse(method.down(mView, mSpannable));
        assertSelection(mSpannable, -1);

        assertFalse(method.left(mView, mSpannable));
        assertSelection(mSpannable, -1);

        assertFalse(method.right(mView, mSpannable));
        assertSelection(mSpannable, -1);
    }

    public void testInitialize() {
        LinkMovementMethod method = new LinkMovementMethod();
        Spannable spannable = new SpannableString("test sequence");
        method.onTakeFocus(null, spannable, View.FOCUS_UP);
        Selection.setSelection(spannable, 0, spannable.length());

        assertSelection(spannable, 0, spannable.length());
        assertTrue("Expected at least 3 spans", 3 <= spannable.getSpans(0, spannable.length(), Object.class).length);
        method.initialize(null, spannable);
        assertSelection(spannable, -1);
        assertEquals(0, spannable.getSpans(0, spannable.length(), Object.class).length);

        try {
            method.initialize(mView, null);
            fail("The method did not throw NullPointerException when param spannable is null.");
        } catch (NullPointerException e) {
            // expected
        }
    }

    private MockClickableSpan markClickable(final int start, final int end) {
        final MockClickableSpan clickableSpan = new MockClickableSpan();
        getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                mSpannable.setSpan(clickableSpan, start, end, Spanned.SPAN_MARK_MARK);
            }
        });
        getInstrumentation().waitForIdleSync();
        return clickableSpan;
    }

    private boolean performMotionOnLine(int line, int action) {
        int x = (mView.getLayout().getLineStart(line) + mView.getLayout().getLineEnd(line)) / 2;
        int y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2;
        long now = SystemClock.uptimeMillis();

        return mMethod.onTouchEvent(mView, mSpannable,
                MotionEvent.obtain(now, now, action, x, y, 0));
    }

    private boolean pressOnLine(int line) {
        return performMotionOnLine(line, MotionEvent.ACTION_DOWN);
    }

    private boolean releaseOnLine(int line) {
        return performMotionOnLine(line, MotionEvent.ACTION_UP);
    }

    private void assertSelection(Spannable spannable, int start, int end) {
        assertEquals(start, Selection.getSelectionStart(spannable));
        assertEquals(end, Selection.getSelectionEnd(spannable));
    }

    private void assertSelection(Spannable spannable, int position) {
        assertSelection(spannable, position, position);
    }

    private void assertSelectClickableLeftToRight(Spannable spannable,
            MockClickableSpan clickableSpan) {
        assertSelection(spannable, spannable.getSpanStart(clickableSpan),
                spannable.getSpanEnd(clickableSpan));
    }

    private void assertSelectClickableRightToLeft(Spannable spannable,
            MockClickableSpan clickableSpan) {
        assertSelection(spannable,  spannable.getSpanEnd(clickableSpan),
                spannable.getSpanStart(clickableSpan));
    }

    private static class MyLinkMovementMethod extends LinkMovementMethod {
        @Override
        protected boolean down(TextView widget, Spannable buffer) {
            return super.down(widget, buffer);
        }

        @Override
        protected boolean left(TextView widget, Spannable buffer) {
            return super.left(widget, buffer);
        }

        @Override
        protected boolean right(TextView widget, Spannable buffer) {
            return super.right(widget, buffer);
        }

        @Override
        protected boolean up(TextView widget, Spannable buffer) {
            return super.up(widget, buffer);
        }
    }

    private static class MockClickableSpan extends ClickableSpan {
        private boolean mHasCalledOnClick;

        @Override
        public void onClick(View widget) {
            mHasCalledOnClick = true;
        }

        public boolean hasCalledOnClick() {
            return mHasCalledOnClick;
        }

        public void reset() {
            mHasCalledOnClick = false;
        }
    }
}
