/*
 * Copyright (C) 2016 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.assertTrue;

import android.text.InputType;
import android.text.method.BaseKeyListener;
import android.view.KeyEvent;
import android.widget.TextView.BufferType;

import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;

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

/**
 * Test forward delete key handling of  {@link android.text.method.BaseKeyListener}.
 */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ForwardDeleteTest extends KeyListenerTestCase {
    private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
        public int getInputType() {
            return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
        }
    };

    // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
    // Then update the state to the result of TextView.
    private void forwardDelete(final EditorState state, int modifiers) throws Throwable {
        mActivityRule.runOnUiThread(() -> {
            mTextView.setText(state.mText, BufferType.EDITABLE);
            mTextView.setKeyListener(mKeyListener);
            mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
        });
        mInstrumentation.waitForIdleSync();
        assertTrue(mTextView.hasWindowFocus());

        final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
        mActivity.runOnUiThread(() -> mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent));
        mInstrumentation.waitForIdleSync();

        state.mText = mTextView.getText();
        state.mSelectionStart = mTextView.getSelectionStart();
        state.mSelectionEnd = mTextView.getSelectionEnd();
    }

    @Test
    public void testCRLF() throws Throwable {
        EditorState state = new EditorState();

        // U+000A is LINE FEED.
        state.setByString("| U+000A");
        forwardDelete(state, 0);
        state.assertEquals("|");

        // U+000D is CARRIAGE RETURN.
        state.setByString("| U+000D");
        forwardDelete(state, 0);
        state.assertEquals("|");

        state.setByString("| U+000D U+000A");
        forwardDelete(state, 0);
        state.assertEquals("|");

        state.setByString("| U+000A U+000D");
        forwardDelete(state, 0);
        state.assertEquals("| U+000D");
        forwardDelete(state, 0);
    }

    @Test
    public void testSurrogatePairs() throws Throwable {
        EditorState state = new EditorState();

        // U+1F441 is EYE
        state.setByString("| U+1F441");
        forwardDelete(state, 0);
        state.assertEquals("|");

        // U+1F5E8 is LEFT SPEECH BUBBLE
        state.setByString("| U+1F441 U+1F5E8");
        forwardDelete(state, 0);
        state.assertEquals("| U+1F5E8");
        forwardDelete(state, 0);
        state.assertEquals("|");
    }

    @Test
    public void testReplacementSpan() throws Throwable {
        EditorState state = new EditorState();

        state.setByString("| 'abc' ( 'de' ) 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("| 'bc' ( 'de' ) 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("| 'c' ( 'de' ) 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("| ( 'de' ) 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("| 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("| 'g'");
        forwardDelete(state, 0);
        state.assertEquals("|");

        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("'abc' | 'fg'");
        forwardDelete(state, 0);
        state.assertEquals("'abc' | 'g'");
        forwardDelete(state, 0);
        state.assertEquals("'abc' |");
        forwardDelete(state, 0);
        state.assertEquals("'abc' |");

        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
        forwardDelete(state, 0);
        state.assertEquals("'ab' | 'g'");
        forwardDelete(state, 0);
        state.assertEquals("'ab' |");
        forwardDelete(state, 0);
        state.assertEquals("'ab' |");
    }

    @Test
    public void testCombiningEnclosingKeycaps() throws Throwable {
        EditorState state = new EditorState();

        // U+20E3 is COMBINING ENCLOSING KEYCAP.
        state.setByString("| '1' U+20E3");
        forwardDelete(state, 0);
        state.assertEquals("|");

        state.setByString("| '1' U+FE0F U+20E3");
        forwardDelete(state, 0);
        state.assertEquals("|");
    }

    @Test
    public void testVariationSelector() throws Throwable {
        EditorState state = new EditorState();

        // U+FE0F is VARIATION SELECTOR-16.
        state.setByString("| '#' U+FE0F");
        forwardDelete(state, 0);
        state.assertEquals("|");

        // U+E0100 is VARIATION SELECTOR-17.
        state.setByString("| U+845B U+E0100");
        forwardDelete(state, 0);
        state.assertEquals("|");
    }

    @Test
    public void testFlags() throws Throwable {
        EditorState state = new EditorState();

        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
        state.setByString("| U+1F1FA U+1F1F8");
        forwardDelete(state, 0);
        state.assertEquals("|");

        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
        forwardDelete(state, 0);
        state.assertEquals("| U+1F1FA U+1F1F8");
        forwardDelete(state, 0);
        state.assertEquals("|");

        // Single tag_base character
        // U+1F3F4 is WAVING BLACK FLAG. This can be a tag_base character.
        state.setByString("| 'a' U+1F3F4 U+1F3F4 'b'");
        forwardDelete(state, 0);
        state.assertEquals("| U+1F3F4 U+1F3F4 'b'");
        forwardDelete(state, 0);
        state.assertEquals("| U+1F3F4 'b'");
        forwardDelete(state, 0);
        state.assertEquals("| 'b'");

        // U+E0067 is TAG LATIN SMALL LETTER G. This can be a part of tag_spec.
        // U+E0062 is TAG LATIN SMALL LETTER B. This can be a part of tag_spec.
        // U+E0073 is TAG LATIN SMALL LETTER S. This can be a part of tag_spec.
        // U+E0063 is TAG LATIN SMALL LETTER C. This can be a part of tag_spec.
        // U+E0074 is TAG LATIN SMALL LETTER T. This can be a part of tag_spec.
        // U+E007F is CANCEL TAG. This is a tag_term character.
        final String scotland = "U+1F3F4 U+E0067 U+E0062 U+E0073 U+E0063 U+E0074 U+E007F ";

        state.setByString("| 'a' " + scotland + scotland + "'b'");
        forwardDelete(state, 0);
        state.assertEquals("| " + scotland + scotland + "'b'");
        forwardDelete(state, 0);
        state.assertEquals("| " + scotland + "'b'");
        forwardDelete(state, 0);
        state.assertEquals("| 'b'");
    }
}
