/*
 * Copyright (C) 2015 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 com.android.server.accessibility;

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Pools;
import android.util.Slog;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;

/**
 * Intercepts key events and forwards them to accessibility manager service.
 */
public class KeyboardInterceptor implements EventStreamTransformation, Handler.Callback {
    private static final int MESSAGE_PROCESS_QUEUED_EVENTS = 1;
    private static final String LOG_TAG = "KeyboardInterceptor";

    private final AccessibilityManagerService mAms;
    private final WindowManagerPolicy mPolicy;
    private final Handler mHandler;

    private EventStreamTransformation mNext;
    private KeyEventHolder mEventQueueStart;
    private KeyEventHolder mEventQueueEnd;

    /**
     * @param service The service to notify of key events
     * @param policy The policy to check for keys that may affect a11y
     */
    public KeyboardInterceptor(AccessibilityManagerService service, WindowManagerPolicy policy) {
        mAms = service;
        mPolicy = policy;
        mHandler = new Handler(this);
    }

    /**
     * @param service The service to notify of key events
     * @param policy The policy to check for keys that may affect a11y
     * @param handler The handler to use. Only used for testing.
     */
    public KeyboardInterceptor(AccessibilityManagerService service, WindowManagerPolicy policy,
            Handler handler) {
        // Can't combine the constructors without making at least mHandler non-final.
        mAms = service;
        mPolicy = policy;
        mHandler = handler;
    }

    @Override
    public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
        if (mNext != null) {
            mNext.onMotionEvent(event, rawEvent, policyFlags);
        }
    }

    @Override
    public void onKeyEvent(KeyEvent event, int policyFlags) {
        /*
         * Certain keys have system-level behavior that affects accessibility services.
         * Let that behavior settle before handling the keys
         */
        long eventDelay = getEventDelay(event, policyFlags);
        if (eventDelay < 0) {
            return;
        }
        if ((eventDelay > 0) || (mEventQueueStart != null))  {
            addEventToQueue(event, policyFlags, eventDelay);
            return;
        }

        mAms.notifyKeyEvent(event, policyFlags);
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (mNext != null) {
            mNext.onAccessibilityEvent(event);
        }
    }

    @Override
    public void setNext(EventStreamTransformation next) {
        mNext = next;
    }

    @Override
    public void clearEvents(int inputSource) {
        if (mNext != null) {
            mNext.clearEvents(inputSource);
        }
    }

    @Override
    public void onDestroy() {
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what != MESSAGE_PROCESS_QUEUED_EVENTS) {
            Slog.e(LOG_TAG, "Unexpected message type");
            return false;
        }
        processQueuedEvents();
        if (mEventQueueStart != null) {
            scheduleProcessQueuedEvents();
        }
        return true;
    }

    private void addEventToQueue(KeyEvent event, int policyFlags, long delay) {
        long dispatchTime = SystemClock.uptimeMillis() + delay;
        if (mEventQueueStart == null) {
            mEventQueueEnd = mEventQueueStart =
                    KeyEventHolder.obtain(event, policyFlags, dispatchTime);
            scheduleProcessQueuedEvents();
            return;
        }
        final KeyEventHolder holder = KeyEventHolder.obtain(event, policyFlags, dispatchTime);
        holder.next = mEventQueueStart;
        mEventQueueStart.previous = holder;
        mEventQueueStart = holder;
    }

    private void scheduleProcessQueuedEvents() {
        if (!mHandler.sendEmptyMessageAtTime(
                MESSAGE_PROCESS_QUEUED_EVENTS, mEventQueueEnd.dispatchTime)) {
            Slog.e(LOG_TAG, "Failed to schedule key event");
        };
    }

    private void processQueuedEvents() {
        final long currentTime = SystemClock.uptimeMillis();
        while ((mEventQueueEnd != null) && (mEventQueueEnd.dispatchTime <= currentTime)) {
            final long eventDelay = getEventDelay(mEventQueueEnd.event, mEventQueueEnd.policyFlags);
            if (eventDelay > 0) {
                // Reschedule the event
                mEventQueueEnd.dispatchTime = currentTime + eventDelay;
                return;
            }
            // We'll either send or drop the event
            if (eventDelay == 0) {
                mAms.notifyKeyEvent(mEventQueueEnd.event, mEventQueueEnd.policyFlags);
            }
            final KeyEventHolder eventToBeRecycled = mEventQueueEnd;
            mEventQueueEnd = mEventQueueEnd.previous;
            if (mEventQueueEnd != null) {
                mEventQueueEnd.next = null;
            }
            eventToBeRecycled.recycle();
            if (mEventQueueEnd == null) {
                mEventQueueStart = null;
            }
        }
    }

    private long getEventDelay(KeyEvent event, int policyFlags) {
        int keyCode = event.getKeyCode();
        if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) || (keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
            return mPolicy.interceptKeyBeforeDispatching(null, event, policyFlags);
        }
        return 0;
    }

    private static class KeyEventHolder {
        private static final int MAX_POOL_SIZE = 32;
        private static final Pools.SimplePool<KeyEventHolder> sPool =
                new Pools.SimplePool<>(MAX_POOL_SIZE);

        public int policyFlags;
        public long dispatchTime;
        public KeyEvent event;
        public KeyEventHolder next;
        public KeyEventHolder previous;

        public static KeyEventHolder obtain(KeyEvent event, int policyFlags, long dispatchTime) {
            KeyEventHolder holder = sPool.acquire();
            if (holder == null) {
                holder = new KeyEventHolder();
            }
            holder.event = KeyEvent.obtain(event);
            holder.policyFlags = policyFlags;
            holder.dispatchTime = dispatchTime;
            return holder;
        }

        public void recycle() {
            event.recycle();
            event = null;
            policyFlags = 0;
            dispatchTime = 0;
            next = null;
            previous = null;
            sPool.release(this);
        }
    }
}
