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

import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.ResultReceiver;
import android.util.Log;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.inputmethod.IMultiClientInputMethodSession;
import com.android.internal.inputmethod.CancellationGroup;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputConnectionWrapper;

import java.lang.ref.WeakReference;

/**
 * Re-dispatches all the incoming per-client events to the specified {@link Looper} thread.
 *
 * <p>There are three types of per-client callbacks.</p>
 *
 * <ul>
 *     <li>{@link IInputMethodSession} - from the IME client</li>
 *     <li>{@link IMultiClientInputMethodSession} - from MultiClientInputMethodManagerService</li>
 *     <li>{@link InputChannel} - from the IME client</li>
 * </ul>
 *
 * <p>This class serializes all the incoming events among those channels onto
 * {@link MultiClientInputMethodServiceDelegate.ClientCallback} on the specified {@link Looper}
 * thread.</p>
 */
final class MultiClientInputMethodClientCallbackAdaptor {
    static final boolean DEBUG = false;
    static final String TAG = MultiClientInputMethodClientCallbackAdaptor.class.getSimpleName();

    private final Object mSessionLock = new Object();
    @GuardedBy("mSessionLock")
    CallbackImpl mCallbackImpl;
    @GuardedBy("mSessionLock")
    InputChannel mReadChannel;
    @GuardedBy("mSessionLock")
    KeyEvent.DispatcherState mDispatcherState;
    @GuardedBy("mSessionLock")
    Handler mHandler;
    @GuardedBy("mSessionLock")
    @Nullable
    InputEventReceiver mInputEventReceiver;

    private final CancellationGroup mCancellationGroup = new CancellationGroup();

    IInputMethodSession.Stub createIInputMethodSession() {
        synchronized (mSessionLock) {
            return new InputMethodSessionImpl(
                    mSessionLock, mCallbackImpl, mHandler, mCancellationGroup);
        }
    }

    IMultiClientInputMethodSession.Stub createIMultiClientInputMethodSession() {
        synchronized (mSessionLock) {
            return new MultiClientInputMethodSessionImpl(
                    mSessionLock, mCallbackImpl, mHandler, mCancellationGroup);
        }
    }

    MultiClientInputMethodClientCallbackAdaptor(
            MultiClientInputMethodServiceDelegate.ClientCallback clientCallback, Looper looper,
            KeyEvent.DispatcherState dispatcherState, InputChannel readChannel) {
        synchronized (mSessionLock) {
            mCallbackImpl = new CallbackImpl(this, clientCallback);
            mDispatcherState = dispatcherState;
            mHandler = new Handler(looper, null, true);
            mReadChannel = readChannel;
            mInputEventReceiver = new ImeInputEventReceiver(mReadChannel, mHandler.getLooper(),
                    mCancellationGroup, mDispatcherState, mCallbackImpl.mOriginalCallback);
        }
    }

    private static final class KeyEventCallbackAdaptor implements KeyEvent.Callback {
        private final MultiClientInputMethodServiceDelegate.ClientCallback mLocalCallback;

        KeyEventCallbackAdaptor(
                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
            mLocalCallback = callback;
        }

        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            return mLocalCallback.onKeyDown(keyCode, event);
        }

        @Override
        public boolean onKeyLongPress(int keyCode, KeyEvent event) {
            return mLocalCallback.onKeyLongPress(keyCode, event);
        }

        @Override
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            return mLocalCallback.onKeyUp(keyCode, event);
        }

        @Override
        public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
            return mLocalCallback.onKeyMultiple(keyCode, event);
        }
    }

    private static final class ImeInputEventReceiver extends InputEventReceiver {
        private final CancellationGroup mCancellationGroupOnFinishSession;
        private final KeyEvent.DispatcherState mDispatcherState;
        private final MultiClientInputMethodServiceDelegate.ClientCallback mClientCallback;
        private final KeyEventCallbackAdaptor mKeyEventCallbackAdaptor;

        ImeInputEventReceiver(InputChannel readChannel, Looper looper,
                CancellationGroup cancellationGroupOnFinishSession,
                KeyEvent.DispatcherState dispatcherState,
                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
            super(readChannel, looper);
            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
            mDispatcherState = dispatcherState;
            mClientCallback = callback;
            mKeyEventCallbackAdaptor = new KeyEventCallbackAdaptor(callback);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            if (mCancellationGroupOnFinishSession.isCanceled()) {
                // The session has been finished.
                finishInputEvent(event, false);
                return;
            }
            boolean handled = false;
            try {
                if (event instanceof KeyEvent) {
                    final KeyEvent keyEvent = (KeyEvent) event;
                    handled = keyEvent.dispatch(mKeyEventCallbackAdaptor, mDispatcherState,
                            mKeyEventCallbackAdaptor);
                } else {
                    final MotionEvent motionEvent = (MotionEvent) event;
                    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
                        handled = mClientCallback.onTrackballEvent(motionEvent);
                    } else {
                        handled = mClientCallback.onGenericMotionEvent(motionEvent);
                    }
                }
            } finally {
                finishInputEvent(event, handled);
            }
        }
    }

    private static final class InputMethodSessionImpl extends IInputMethodSession.Stub {
        private final Object mSessionLock;
        @GuardedBy("mSessionLock")
        private CallbackImpl mCallbackImpl;
        @GuardedBy("mSessionLock")
        private Handler mHandler;
        private final CancellationGroup mCancellationGroupOnFinishSession;

        InputMethodSessionImpl(Object lock, CallbackImpl callback, Handler handler,
                CancellationGroup cancellationGroupOnFinishSession) {
            mSessionLock = lock;
            mCallbackImpl = callback;
            mHandler = handler;
            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
        }

        @Override
        public void updateExtractedText(int token, ExtractedText text) {
            reportNotSupported();
        }

        @Override
        public void updateSelection(int oldSelStart, int oldSelEnd,
                int newSelStart, int newSelEnd,
                int candidatesStart, int candidatesEnd) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                final SomeArgs args = SomeArgs.obtain();
                args.argi1 = oldSelStart;
                args.argi2 = oldSelEnd;
                args.argi3 = newSelStart;
                args.argi4 = newSelEnd;
                args.argi5 = candidatesStart;
                args.argi6 = candidatesEnd;
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::updateSelection, mCallbackImpl, args));
            }
        }

        @Override
        public void viewClicked(boolean focusChanged) {
            reportNotSupported();
        }

        @Override
        public void updateCursor(Rect newCursor) {
            reportNotSupported();
        }

        @Override
        public void displayCompletions(CompletionInfo[] completions) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::displayCompletions, mCallbackImpl, completions));
            }
        }

        @Override
        public void appPrivateCommand(String action, Bundle data) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::appPrivateCommand, mCallbackImpl, action, data));
            }
        }

        @Override
        public void toggleSoftInput(int showFlags, int hideFlags) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::toggleSoftInput, mCallbackImpl, showFlags,
                        hideFlags));
            }
        }

        @Override
        public void finishSession() {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mCancellationGroupOnFinishSession.cancelAll();
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::finishSession, mCallbackImpl));
                mCallbackImpl = null;
                mHandler = null;
            }
        }

        @Override
        public void updateCursorAnchorInfo(CursorAnchorInfo info) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::updateCursorAnchorInfo, mCallbackImpl, info));
            }
        }

        @Override
        public final void notifyImeHidden() {
            // no-op for multi-session since IME is responsible controlling navigation bar buttons.
            reportNotSupported();
        }

        @Override
        public void removeImeSurface() {
            // no-op for multi-session
            reportNotSupported();
        }
    }

    private static final class MultiClientInputMethodSessionImpl
            extends IMultiClientInputMethodSession.Stub {
        private final Object mSessionLock;
        @GuardedBy("mSessionLock")
        private CallbackImpl mCallbackImpl;
        @GuardedBy("mSessionLock")
        private Handler mHandler;
        private final CancellationGroup mCancellationGroupOnFinishSession;

        MultiClientInputMethodSessionImpl(Object lock, CallbackImpl callback,
                Handler handler, CancellationGroup cancellationGroupOnFinishSession) {
            mSessionLock = lock;
            mCallbackImpl = callback;
            mHandler = handler;
            mCancellationGroupOnFinishSession = cancellationGroupOnFinishSession;
        }

        @Override
        public void startInputOrWindowGainedFocus(@Nullable IInputContext inputContext,
                int missingMethods, @Nullable EditorInfo editorInfo, int controlFlags,
                @SoftInputModeFlags int softInputMode, int windowHandle) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                final SomeArgs args = SomeArgs.obtain();
                // TODO(Bug 119211536): Remove dependency on AbstractInputMethodService from ICW
                final WeakReference<AbstractInputMethodService> fakeIMS =
                        new WeakReference<>(null);
                args.arg1 = (inputContext == null) ? null
                        : new InputConnectionWrapper(fakeIMS, inputContext, missingMethods,
                                mCancellationGroupOnFinishSession);
                args.arg2 = editorInfo;
                args.argi1 = controlFlags;
                args.argi2 = softInputMode;
                args.argi3 = windowHandle;
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::startInputOrWindowGainedFocus, mCallbackImpl, args));
            }
        }

        @Override
        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::showSoftInput, mCallbackImpl, flags,
                        resultReceiver));
            }
        }

        @Override
        public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
            synchronized (mSessionLock) {
                if (mCallbackImpl == null || mHandler == null) {
                    return;
                }
                mHandler.sendMessage(PooledLambda.obtainMessage(
                        CallbackImpl::hideSoftInput, mCallbackImpl, flags,
                        resultReceiver));
            }
        }
    }

    /**
     * The maim part of adaptor to {@link MultiClientInputMethodServiceDelegate.ClientCallback}.
     */
    @WorkerThread
    private static final class CallbackImpl {
        private final MultiClientInputMethodClientCallbackAdaptor mCallbackAdaptor;
        private final MultiClientInputMethodServiceDelegate.ClientCallback mOriginalCallback;
        private boolean mFinished = false;

        CallbackImpl(MultiClientInputMethodClientCallbackAdaptor callbackAdaptor,
                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
            mCallbackAdaptor = callbackAdaptor;
            mOriginalCallback = callback;
        }

        void updateSelection(SomeArgs args) {
            try {
                if (mFinished) {
                    return;
                }
                mOriginalCallback.onUpdateSelection(args.argi1, args.argi2, args.argi3,
                        args.argi4, args.argi5, args.argi6);
            } finally {
                args.recycle();
            }
        }

        void displayCompletions(CompletionInfo[] completions) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onDisplayCompletions(completions);
        }

        void appPrivateCommand(String action, Bundle data) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onAppPrivateCommand(action, data);
        }

        void toggleSoftInput(int showFlags, int hideFlags) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onToggleSoftInput(showFlags, hideFlags);
        }

        void finishSession() {
            if (mFinished) {
                return;
            }
            mFinished = true;
            mOriginalCallback.onFinishSession();
            synchronized (mCallbackAdaptor.mSessionLock) {
                mCallbackAdaptor.mDispatcherState = null;
                if (mCallbackAdaptor.mReadChannel != null) {
                    mCallbackAdaptor.mReadChannel.dispose();
                    mCallbackAdaptor.mReadChannel = null;
                }
                mCallbackAdaptor.mInputEventReceiver = null;
            }
        }

        void updateCursorAnchorInfo(CursorAnchorInfo info) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onUpdateCursorAnchorInfo(info);
        }

        void startInputOrWindowGainedFocus(SomeArgs args) {
            try {
                if (mFinished) {
                    return;
                }
                final InputConnectionWrapper inputConnection = (InputConnectionWrapper) args.arg1;
                final EditorInfo editorInfo = (EditorInfo) args.arg2;
                final int startInputFlags = args.argi1;
                final int softInputMode = args.argi2;
                final int windowHandle = args.argi3;
                mOriginalCallback.onStartInputOrWindowGainedFocus(inputConnection, editorInfo,
                        startInputFlags, softInputMode, windowHandle);
            } finally {
                args.recycle();
            }
        }

        void showSoftInput(int flags, ResultReceiver resultReceiver) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onShowSoftInput(flags, resultReceiver);
        }

        void hideSoftInput(int flags, ResultReceiver resultReceiver) {
            if (mFinished) {
                return;
            }
            mOriginalCallback.onHideSoftInput(flags, resultReceiver);
        }
    }

    private static void reportNotSupported() {
        if (DEBUG) {
            Log.d(TAG, Debug.getCaller() + " is not supported");
        }
    }
}
