/*
 * 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 com.android.server.tv;

import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.server.SystemService;
import com.android.server.Watchdog;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

/**
 * TvRemoteService represents a system service that allows a connected
 * remote control (emote) service to inject white-listed input events
 * and call other specified methods for functioning as an emote service.
 * <p/>
 * This service is intended for use only by white-listed packages.
 */
public class TvRemoteService extends SystemService implements Watchdog.Monitor {
    private static final String TAG = "TvRemoteService";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG_KEYS = false;

    private Map<IBinder, UinputBridge> mBridgeMap = new ArrayMap();
    private Map<IBinder, TvRemoteProviderProxy> mProviderMap = new ArrayMap();
    private ArrayList<TvRemoteProviderProxy> mProviderList = new ArrayList<>();

    /**
     * State guarded by mLock.
     *  This is the second lock in sequence for an incoming call.
     *  The first lock is always {@link TvRemoteProviderProxy#mLock}
     *
     *  There are currently no methods that break this sequence.
     *  Special note:
     *  Outgoing call informInputBridgeConnected(), which is called from
     *  openInputBridgeInternalLocked() uses a handler thereby relinquishing held locks.
     */
    private final Object mLock = new Object();

    public final UserHandler mHandler;

    public TvRemoteService(Context context) {
        super(context);
        mHandler = new UserHandler(new UserProvider(TvRemoteService.this), context);
        Watchdog.getInstance().addMonitor(this);
    }

    @Override
    public void onStart() {
        if (DEBUG) Slog.d(TAG, "onStart()");
    }

    @Override
    public void monitor() {
        synchronized (mLock) { /* check for deadlock */ }
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
            if (DEBUG) Slog.d(TAG, "PHASE_THIRD_PARTY_APPS_CAN_START");
            mHandler.sendEmptyMessage(UserHandler.MSG_START);
        }
    }

    //Outgoing calls.
    private void informInputBridgeConnected(IBinder token) {
        mHandler.obtainMessage(UserHandler.MSG_INPUT_BRIDGE_CONNECTED, 0, 0, token).sendToTarget();
    }

    // Incoming calls.
    private void openInputBridgeInternalLocked(TvRemoteProviderProxy provider, IBinder token,
                                               String name, int width, int height,
                                               int maxPointers) {
        if (DEBUG) {
            Slog.d(TAG, "openInputBridgeInternalLocked(), token: " + token + ", name: " + name +
                    ", width: " + width + ", height: " + height + ", maxPointers: " + maxPointers);
        }

        try {
            //Create a new bridge, if one does not exist already
            if (mBridgeMap.containsKey(token)) {
                if (DEBUG) Slog.d(TAG, "RemoteBridge already exists");
                // Respond back with success.
                informInputBridgeConnected(token);
                return;
            }

            UinputBridge inputBridge = new UinputBridge(token, name, width, height, maxPointers);

            mBridgeMap.put(token, inputBridge);
            mProviderMap.put(token, provider);

            // Respond back with success.
            informInputBridgeConnected(token);

        } catch (IOException ioe) {
            Slog.e(TAG, "Cannot create device for " + name);
        }
    }

    private void closeInputBridgeInternalLocked(IBinder token) {
        if (DEBUG) {
            Slog.d(TAG, "closeInputBridgeInternalLocked(), token: " + token);
        }

        // Close an existing RemoteBridge
        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.close(token);
        }

        mBridgeMap.remove(token);
    }


    private void clearInputBridgeInternalLocked(IBinder token) {
        if (DEBUG) {
            Slog.d(TAG, "clearInputBridgeInternalLocked(), token: " + token);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.clear(token);
        }
    }

    private void sendTimeStampInternalLocked(IBinder token, long timestamp) {
        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendTimestamp(token, timestamp);
        }
    }

    private void sendKeyDownInternalLocked(IBinder token, int keyCode) {
        if (DEBUG_KEYS) {
            Slog.d(TAG, "sendKeyDownInternalLocked(), token: " + token + ", keyCode: " + keyCode);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendKeyDown(token, keyCode);
        }
    }

    private void sendKeyUpInternalLocked(IBinder token, int keyCode) {
        if (DEBUG_KEYS) {
            Slog.d(TAG, "sendKeyUpInternalLocked(), token: " + token + ", keyCode: " + keyCode);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendKeyUp(token, keyCode);
        }
    }

    private void sendPointerDownInternalLocked(IBinder token, int pointerId, int x, int y) {
        if (DEBUG_KEYS) {
            Slog.d(TAG, "sendPointerDownInternalLocked(), token: " + token + ", pointerId: " +
                    pointerId + ", x: " + x + ", y: " + y);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendPointerDown(token, pointerId, x, y);
        }
    }

    private void sendPointerUpInternalLocked(IBinder token, int pointerId) {
        if (DEBUG_KEYS) {
            Slog.d(TAG, "sendPointerUpInternalLocked(), token: " + token + ", pointerId: " +
                    pointerId);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendPointerUp(token, pointerId);
        }
    }

    private void sendPointerSyncInternalLocked(IBinder token) {
        if (DEBUG_KEYS) {
            Slog.d(TAG, "sendPointerSyncInternalLocked(), token: " + token);
        }

        UinputBridge inputBridge = mBridgeMap.get(token);
        if (inputBridge != null) {
            inputBridge.sendPointerSync(token);
        }
    }

    private final class UserHandler extends Handler {

        public static final int MSG_START = 1;
        public static final int MSG_INPUT_BRIDGE_CONNECTED = 2;

        private final TvRemoteProviderWatcher mWatcher;
        private boolean mRunning;

        public UserHandler(UserProvider provider, Context context) {
            super(Looper.getMainLooper(), null, true);
            mWatcher = new TvRemoteProviderWatcher(context, provider, this);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_START: {
                    start();
                    break;
                }
                case MSG_INPUT_BRIDGE_CONNECTED: {
                    IBinder token = (IBinder) msg.obj;
                    TvRemoteProviderProxy provider = mProviderMap.get(token);
                    if (provider != null) {
                        provider.inputBridgeConnected(token);
                    }
                    break;
                }
            }
        }

        private void start() {
            if (!mRunning) {
                mRunning = true;
                mWatcher.start(); // also starts all providers
            }
        }
    }

    private final class UserProvider implements TvRemoteProviderWatcher.ProviderMethods,
            TvRemoteProviderProxy.ProviderMethods {

        private final TvRemoteService mService;

        public UserProvider(TvRemoteService service) {
            mService = service;
        }

        @Override
        public void openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
                                    int width, int height, int maxPointers) {
            if (DEBUG) {
                Slog.d(TAG, "openInputBridge(), token: " + token +
                        ", name: " + name + ", width: " + width +
                        ", height: " + height + ", maxPointers: " + maxPointers);
            }

            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.openInputBridgeInternalLocked(provider, token, name, width, height,
                            maxPointers);
                }
            }
        }

        @Override
        public void closeInputBridge(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG) Slog.d(TAG, "closeInputBridge(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.closeInputBridgeInternalLocked(token);
                    mProviderMap.remove(token);
                }
            }
        }

        @Override
        public void clearInputBridge(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG) Slog.d(TAG, "clearInputBridge(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.clearInputBridgeInternalLocked(token);
                }
            }
        }

        @Override
        public void sendTimeStamp(TvRemoteProviderProxy provider, IBinder token, long timestamp) {
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendTimeStampInternalLocked(token, timestamp);
                }
            }
        }

        @Override
        public void sendKeyDown(TvRemoteProviderProxy provider, IBinder token, int keyCode) {
            if (DEBUG_KEYS) {
                Slog.d(TAG, "sendKeyDown(), token: " + token + ", keyCode: " + keyCode);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendKeyDownInternalLocked(token, keyCode);
                }
            }
        }

        @Override
        public void sendKeyUp(TvRemoteProviderProxy provider, IBinder token, int keyCode) {
            if (DEBUG_KEYS) {
                Slog.d(TAG, "sendKeyUp(), token: " + token + ", keyCode: " + keyCode);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendKeyUpInternalLocked(token, keyCode);
                }
            }
        }

        @Override
        public void sendPointerDown(TvRemoteProviderProxy provider, IBinder token, int pointerId,
                                    int x, int y) {
            if (DEBUG_KEYS) {
                Slog.d(TAG, "sendPointerDown(), token: " + token + ", pointerId: " + pointerId);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerDownInternalLocked(token, pointerId, x, y);
                }
            }
        }

        @Override
        public void sendPointerUp(TvRemoteProviderProxy provider, IBinder token, int pointerId) {
            if (DEBUG_KEYS) {
                Slog.d(TAG, "sendPointerUp(), token: " + token + ", pointerId: " + pointerId);
            }
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerUpInternalLocked(token, pointerId);
                }
            }
        }

        @Override
        public void sendPointerSync(TvRemoteProviderProxy provider, IBinder token) {
            if (DEBUG_KEYS) Slog.d(TAG, "sendPointerSync(), token: " + token);
            synchronized (mLock) {
                if (mProviderList.contains(provider)) {
                    mService.sendPointerSyncInternalLocked(token);
                }
            }
        }

        @Override
        public void addProvider(TvRemoteProviderProxy provider) {
            if (DEBUG) Slog.d(TAG, "addProvider " + provider);
            synchronized (mLock) {
                provider.setProviderSink(this);
                mProviderList.add(provider);
                Slog.d(TAG, "provider: " + provider.toString());
            }
        }

        @Override
        public void removeProvider(TvRemoteProviderProxy provider) {
            if (DEBUG) Slog.d(TAG, "removeProvider " + provider);
            synchronized (mLock) {
                if (mProviderList.remove(provider) == false) {
                    Slog.e(TAG, "Unknown provider " + provider);
                }
            }
        }
    }
}
