// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content.browser.input;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;

import org.junit.Assert;

import org.chromium.base.ThreadUtils;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.SelectionPopupController;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.DOMUtils;
import org.chromium.content.browser.test.util.JavaScriptUtils;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content.browser.test.util.TestInputMethodManagerWrapper;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell_apk.ContentShellActivityTestRule;
import org.chromium.ui.base.ime.TextInputType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

/**
 * Integration tests for text input for Android L (or above) features.
 */
class ImeActivityTestRule extends ContentShellActivityTestRule {
    private ChromiumBaseInputConnection mConnection;
    private TestInputConnectionFactory mConnectionFactory;
    private ImeAdapter mImeAdapter;

    static final String INPUT_FORM_HTML = "content/test/data/android/input/input_forms.html";

    private ContentViewCore mContentViewCore;
    private SelectionPopupController mSelectionPopupController;
    private TestCallbackHelperContainer mCallbackContainer;
    private TestInputMethodManagerWrapper mInputMethodManagerWrapper;

    public void setUp() throws Exception {
        launchContentShellWithUrlSync(INPUT_FORM_HTML);
        mContentViewCore = getContentViewCore();
        mSelectionPopupController = mContentViewCore.getSelectionPopupControllerForTesting();
        mInputMethodManagerWrapper = new TestInputMethodManagerWrapper(mContentViewCore) {
            private boolean mExpectsSelectionOutsideComposition;

            @Override
            public void expectsSelectionOutsideComposition() {
                mExpectsSelectionOutsideComposition = true;
            }

            @Override
            public void onUpdateSelection(
                    Range oldSel, Range oldComp, Range newSel, Range newComp) {
                // We expect that selection will be outside composition in some cases. Keyboard
                // app will not finish composition in this case.
                if (mExpectsSelectionOutsideComposition) {
                    mExpectsSelectionOutsideComposition = false;
                    return;
                }
                if (oldComp == null || oldComp.start() == oldComp.end()
                        || newComp.start() == newComp.end()) {
                    return;
                }
                // This emulates keyboard app's behavior that finishes composition when
                // selection is outside composition.
                if (!newSel.intersects(newComp)) {
                    try {
                        finishComposingText();
                    } catch (Exception e) {
                        e.printStackTrace();
                        Assert.fail();
                    }
                }
            }
        };
        getImeAdapter().setInputMethodManagerWrapperForTest(mInputMethodManagerWrapper);
        Assert.assertEquals(0, mInputMethodManagerWrapper.getShowSoftInputCounter());
        mConnectionFactory =
                new TestInputConnectionFactory(getImeAdapter().getInputConnectionFactoryForTest());
        getImeAdapter().setInputConnectionFactory(mConnectionFactory);

        mCallbackContainer = new TestCallbackHelperContainer(mContentViewCore);
        DOMUtils.waitForNonZeroNodeBounds(getWebContents(), "input_text");
        boolean result = DOMUtils.clickNode(mContentViewCore, "input_text");

        Assert.assertEquals("Failed to dispatch touch event.", true, result);
        assertWaitForKeyboardStatus(true);

        mConnection = getInputConnection();
        mImeAdapter = getImeAdapter();

        waitForKeyboardStates(1, 0, 1, new Integer[] {TextInputType.TEXT});
        Assert.assertEquals(0, mConnectionFactory.getOutAttrs().initialSelStart);
        Assert.assertEquals(0, mConnectionFactory.getOutAttrs().initialSelEnd);

        waitForEventLogs("selectionchange");
        clearEventLogs();

        waitAndVerifyUpdateSelection(0, 0, 0, -1, -1);
        resetAllStates();
    }

    SelectionPopupController getSelectionPopupController() {
        return mSelectionPopupController;
    }

    TestCallbackHelperContainer getTestCallBackHelperContainer() {
        return mCallbackContainer;
    }

    ChromiumBaseInputConnection getConnection() {
        return mConnection;
    }

    TestInputMethodManagerWrapper getInputMethodManagerWrapper() {
        return mInputMethodManagerWrapper;
    }

    TestInputConnectionFactory getConnectionFactory() {
        return mConnectionFactory;
    }

    void fullyLoadUrl(final String url) throws Throwable {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                getActivity().getActiveShell().loadUrl(url);
            }
        });
        waitForActiveShellToBeDoneLoading();
    }

    void clearEventLogs() throws Exception {
        final String code = "clearEventLogs()";
        JavaScriptUtils.executeJavaScriptAndWaitForResult(
                getContentViewCore().getWebContents(), code);
    }

    void waitForEventLogs(String expectedLogs) throws Exception {
        final String code = "getEventLogs()";
        final String sanitizedExpectedLogs = "\"" + expectedLogs + "\"";
        Assert.assertEquals(sanitizedExpectedLogs,
                JavaScriptUtils.executeJavaScriptAndWaitForResult(
                        getContentViewCore().getWebContents(), code));
    }

    void assertTextsAroundCursor(CharSequence before, CharSequence selected, CharSequence after)
            throws Exception {
        Assert.assertEquals(before, getTextBeforeCursor(100, 0));
        Assert.assertEquals(selected, getSelectedText(0));
        Assert.assertEquals(after, getTextAfterCursor(100, 0));
    }

    void waitForKeyboardStates(int show, int hide, int restart, Integer[] history) {
        final String expected = stringifyKeyboardStates(show, hide, restart, history);
        CriteriaHelper.pollUiThread(Criteria.equals(expected, new Callable<String>() {
            @Override
            public String call() {
                return getKeyboardStates();
            }
        }));
    }

    void resetAllStates() {
        mInputMethodManagerWrapper.reset();
        mConnectionFactory.clearTextInputTypeHistory();
    }

    String getKeyboardStates() {
        int showCount = mInputMethodManagerWrapper.getShowSoftInputCounter();
        int hideCount = mInputMethodManagerWrapper.getHideSoftInputCounter();
        int restartCount = mInputMethodManagerWrapper.getRestartInputCounter();
        Integer[] history = mConnectionFactory.getTextInputTypeHistory();
        return stringifyKeyboardStates(showCount, hideCount, restartCount, history);
    }

    String stringifyKeyboardStates(int show, int hide, int restart, Integer[] history) {
        return "show count: " + show + ", hide count: " + hide + ", restart count: " + restart
                + ", input type history: " + Arrays.deepToString(history);
    }

    void performEditorAction(final int action) {
        mConnection.performEditorAction(action);
    }

    void performGo(TestCallbackHelperContainer testCallbackHelperContainer) throws Throwable {
        final InputConnection inputConnection = mConnection;
        final Callable<Void> callable = new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                inputConnection.performEditorAction(EditorInfo.IME_ACTION_GO);
                return null;
            }
        };

        handleBlockingCallbackAction(
                testCallbackHelperContainer.getOnPageFinishedHelper(), new Runnable() {
                    @Override
                    public void run() {
                        try {
                            runBlockingOnImeThread(callable);
                        } catch (Exception e) {
                            e.printStackTrace();
                            Assert.fail();
                        }
                    }
                });
    }

    void assertWaitForKeyboardStatus(final boolean show) {
        CriteriaHelper.pollUiThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                // We do not check the other way around: in some cases we need to keep
                // input connection even when the last known status is 'hidden'.
                if (show && getInputConnection() == null) {
                    updateFailureReason("input connection should not be null.");
                    return false;
                }
                updateFailureReason("expected show: " + show);
                return show == mInputMethodManagerWrapper.isShowWithoutHideOutstanding();
            }
        });
    }

    void assertWaitForSelectActionBarStatus(final boolean show) {
        CriteriaHelper.pollUiThread(Criteria.equals(show, new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return mContentViewCore.isSelectActionBarShowing();
            }
        }));
    }

    void waitAndVerifyUpdateSelection(final int index, final int selectionStart,
            final int selectionEnd, final int compositionStart, final int compositionEnd) {
        final List<Pair<Range, Range>> states = mInputMethodManagerWrapper.getUpdateSelectionList();
        CriteriaHelper.pollUiThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                return states.size() > index;
            }
        });
        Pair<Range, Range> selection = states.get(index);
        Assert.assertEquals(selectionStart, selection.first.start());
        Assert.assertEquals(selectionEnd, selection.first.end());
        Assert.assertEquals(compositionStart, selection.second.start());
        Assert.assertEquals(compositionEnd, selection.second.end());
    }

    void resetUpdateSelectionList() {
        mInputMethodManagerWrapper.getUpdateSelectionList().clear();
    }

    void assertClipboardContents(final Activity activity, final String expectedContents) {
        CriteriaHelper.pollUiThread(new Criteria() {
            @Override
            public boolean isSatisfied() {
                ClipboardManager clipboardManager =
                        (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
                ClipData clip = clipboardManager.getPrimaryClip();
                return clip != null && clip.getItemCount() == 1
                        && TextUtils.equals(clip.getItemAt(0).getText(), expectedContents);
            }
        });
    }

    ImeAdapter getImeAdapter() {
        return mContentViewCore.getImeAdapterForTest();
    }

    ChromiumBaseInputConnection getInputConnection() {
        try {
            return ThreadUtils.runOnUiThreadBlocking(new Callable<ChromiumBaseInputConnection>() {
                @Override
                public ChromiumBaseInputConnection call() {
                    return mContentViewCore.getImeAdapterForTest().getInputConnectionForTest();
                }
            });
        } catch (ExecutionException e) {
            e.printStackTrace();
            Assert.fail();
            return null;
        }
    }

    void restartInput() {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                mImeAdapter.restartInput();
            }
        });
    }

    // After calling this method, we should call assertClipboardContents() to wait for the clipboard
    // to get updated. See cubug.com/621046
    void copy() {
        final WebContents webContents = getWebContents();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                webContents.copy();
            }
        });
    }

    void cut() {
        final WebContents webContents = getWebContents();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                webContents.cut();
            }
        });
    }

    void setClip(final CharSequence text) {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                final ClipboardManager clipboardManager =
                        (ClipboardManager) getActivity().getSystemService(
                                Context.CLIPBOARD_SERVICE);
                clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text));
            }
        });
    }

    void paste() {
        final WebContents webContents = getWebContents();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                webContents.paste();
            }
        });
    }

    void selectAll() {
        final WebContents webContents = getWebContents();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                webContents.selectAll();
            }
        });
    }

    void collapseSelection() {
        final WebContents webContents = getWebContents();
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                webContents.collapseSelection();
            }
        });
    }

    /**
     * Run the {@Callable} on IME thread (or UI thread if not applicable).
     * @param c The callable
     * @return The result from running the callable.
     */
    <T> T runBlockingOnImeThread(Callable<T> c) throws Exception {
        return ImeTestUtils.runBlockingOnHandler(mConnectionFactory.getHandler(), c);
    }

    boolean beginBatchEdit() throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.beginBatchEdit();
            }
        });
    }

    boolean endBatchEdit() throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.endBatchEdit();
            }
        });
    }

    boolean commitText(final CharSequence text, final int newCursorPosition) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.commitText(text, newCursorPosition);
            }
        });
    }

    boolean setSelection(final int start, final int end) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.setSelection(start, end);
            }
        });
    }

    boolean setComposingRegion(final int start, final int end) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.setComposingRegion(start, end);
            }
        });
    }

    protected boolean setComposingText(final CharSequence text, final int newCursorPosition)
            throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.setComposingText(text, newCursorPosition);
            }
        });
    }

    boolean finishComposingText() throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.finishComposingText();
            }
        });
    }

    boolean deleteSurroundingText(final int before, final int after) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.deleteSurroundingText(before, after);
            }
        });
    }

    // Note that deleteSurroundingTextInCodePoints() was introduced in Android N (Api level 24), but
    // the Android repository used in Chrome is behind that (level 23). So this function can't be
    // called by keyboard apps currently.
    @TargetApi(24)
    boolean deleteSurroundingTextInCodePoints(final int before, final int after) throws Exception {
        final ThreadedInputConnection connection = (ThreadedInputConnection) mConnection;
        return runBlockingOnImeThread(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return connection.deleteSurroundingTextInCodePoints(before, after);
            }
        });
    }

    CharSequence getTextBeforeCursor(final int length, final int flags) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<CharSequence>() {
            @Override
            public CharSequence call() {
                return connection.getTextBeforeCursor(length, flags);
            }
        });
    }

    CharSequence getSelectedText(final int flags) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<CharSequence>() {
            @Override
            public CharSequence call() {
                return connection.getSelectedText(flags);
            }
        });
    }

    CharSequence getTextAfterCursor(final int length, final int flags) throws Exception {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<CharSequence>() {
            @Override
            public CharSequence call() {
                return connection.getTextAfterCursor(length, flags);
            }
        });
    }

    int getCursorCapsMode(final int reqModes) throws Throwable {
        final ChromiumBaseInputConnection connection = mConnection;
        return runBlockingOnImeThread(new Callable<Integer>() {
            @Override
            public Integer call() {
                return connection.getCursorCapsMode(reqModes);
            }
        });
    }

    void dispatchKeyEvent(final KeyEvent event) {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                mImeAdapter.dispatchKeyEvent(event);
            }
        });
    }

    /**
     * Focus element, wait for a single state update, reset state update list.
     * @param id ID of the element to focus.
     */
    void focusElementAndWaitForStateUpdate(String id)
            throws InterruptedException, TimeoutException {
        resetAllStates();
        focusElement(id);
        waitAndVerifyUpdateSelection(0, 0, 0, -1, -1);
        resetAllStates();
    }

    void focusElement(final String id) throws InterruptedException, TimeoutException {
        focusElement(id, true);
    }

    void focusElement(final String id, boolean shouldShowKeyboard)
            throws InterruptedException, TimeoutException {
        DOMUtils.focusNode(getWebContents(), id);
        assertWaitForKeyboardStatus(shouldShowKeyboard);
        CriteriaHelper.pollInstrumentationThread(Criteria.equals(id, new Callable<String>() {
            @Override
            public String call() throws Exception {
                return DOMUtils.getFocusedNode(getWebContents());
            }
        }));
        // When we focus another element, the connection may be recreated.
        mConnection = getInputConnection();
    }

    static class TestInputConnectionFactory implements ChromiumBaseInputConnection.Factory {
        private final ChromiumBaseInputConnection.Factory mFactory;

        private final List<Integer> mTextInputTypeList = new ArrayList<>();
        private EditorInfo mOutAttrs;

        public TestInputConnectionFactory(ChromiumBaseInputConnection.Factory factory) {
            mFactory = factory;
        }

        @Override
        public ChromiumBaseInputConnection initializeAndGet(View view, ImeAdapter imeAdapter,
                int inputType, int inputFlags, int inputMode, int selectionStart, int selectionEnd,
                EditorInfo outAttrs) {
            mTextInputTypeList.add(inputType);
            mOutAttrs = outAttrs;
            return mFactory.initializeAndGet(view, imeAdapter, inputType, inputFlags, inputMode,
                    selectionStart, selectionEnd, outAttrs);
        }

        @Override
        public Handler getHandler() {
            return mFactory.getHandler();
        }

        public Integer[] getTextInputTypeHistory() {
            Integer[] result = new Integer[mTextInputTypeList.size()];
            mTextInputTypeList.toArray(result);
            return result;
        }

        public void clearTextInputTypeHistory() {
            mTextInputTypeList.clear();
        }

        public EditorInfo getOutAttrs() {
            return mOutAttrs;
        }

        @Override
        public void onWindowFocusChanged(boolean gainFocus) {
            mFactory.onWindowFocusChanged(gainFocus);
        }

        @Override
        public void onViewFocusChanged(boolean gainFocus) {
            mFactory.onViewFocusChanged(gainFocus);
        }

        @Override
        public void onViewAttachedToWindow() {
            mFactory.onViewAttachedToWindow();
        }

        @Override
        public void onViewDetachedFromWindow() {
            mFactory.onViewDetachedFromWindow();
        }
    }
}
