/*
 * 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.car;

import android.car.CarProjectionManager;
import android.car.ICarProjection;
import android.car.ICarProjectionListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.KeyEvent;

import java.io.PrintWriter;

/**
 * Car projection service allows to bound to projected app to boost it prioirity.
 * It also enables proejcted applications to handle voice action requests.
 */
class CarProjectionService extends ICarProjection.Stub implements CarServiceBase,
        BinderInterfaceContainer.BinderEventHandler<ICarProjectionListener> {
    private final ListenerHolder mAllListeners;
    private final CarInputService mCarInputService;
    private final Context mContext;

    private final CarInputService.KeyEventListener mVoiceAssistantKeyListener =
            new CarInputService.KeyEventListener() {
                @Override
                public boolean onKeyEvent(KeyEvent event) {
                    handleVoiceAssitantRequest(false);
                    return true;
                }
            };

    private final CarInputService.KeyEventListener mLongVoiceAssistantKeyListener =
            new CarInputService.KeyEventListener() {
                @Override
                public boolean onKeyEvent(KeyEvent event) {
                    handleVoiceAssitantRequest(true);
                    return true;
                }
            };

    private final ServiceConnection mConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName className, IBinder service) {
                synchronized (CarProjectionService.this) {
                    mBound = true;
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName className) {
                // Service has crashed.
                Log.w(CarLog.TAG_PROJECTION, "Service disconnected: " + className);
                synchronized (CarProjectionService.this) {
                    mRegisteredService = null;
                }
                unbindServiceIfBound();
            }
        };

    private boolean mBound;
    private Intent mRegisteredService;

    CarProjectionService(Context context, CarInputService carInputService) {
        mContext = context;
        mCarInputService = carInputService;
        mAllListeners = new ListenerHolder(this);
    }

    @Override
    public void registerProjectionRunner(Intent serviceIntent) {
        // We assume one active projection app running in the system at one time.
        synchronized (this) {
            if (serviceIntent.filterEquals(mRegisteredService)) {
                return;
            }
            if (mRegisteredService != null) {
                Log.w(CarLog.TAG_PROJECTION, "Registering new service[" + serviceIntent
                        + "] while old service[" + mRegisteredService + "] is still running");
            }
            unbindServiceIfBound();
        }
        bindToService(serviceIntent);
    }

    @Override
    public void unregisterProjectionRunner(Intent serviceIntent) {
        synchronized (this) {
            if (!serviceIntent.filterEquals(mRegisteredService)) {
                Log.w(CarLog.TAG_PROJECTION, "Request to unbind unregistered service["
                        + serviceIntent + "]. Registered service[" + mRegisteredService + "]");
                return;
            }
            mRegisteredService = null;
        }
        unbindServiceIfBound();
    }

    private void bindToService(Intent serviceIntent) {
        synchronized (this) {
            mRegisteredService = serviceIntent;
        }
        UserHandle userHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid());
        mContext.startServiceAsUser(serviceIntent, userHandle);
        mContext.bindServiceAsUser(serviceIntent, mConnection, Context.BIND_IMPORTANT, userHandle);
    }

    private void unbindServiceIfBound() {
        synchronized (this) {
            if (!mBound) {
                return;
            }
            mBound = false;
        }
        mContext.unbindService(mConnection);
    }

    private synchronized void handleVoiceAssitantRequest(boolean isTriggeredByLongPress) {
        for (BinderInterfaceContainer.BinderInterface<ICarProjectionListener> listener :
                 mAllListeners.getInterfaces()) {
            ListenerInfo listenerInfo = (ListenerInfo) listener;
            if ((listenerInfo.hasFilter(CarProjectionManager.PROJECTION_LONG_PRESS_VOICE_SEARCH)
                    && isTriggeredByLongPress)
                    || (listenerInfo.hasFilter(CarProjectionManager.PROJECTION_VOICE_SEARCH)
                    && !isTriggeredByLongPress)) {
                dispatchVoiceAssistantRequest(listenerInfo.binderInterface, isTriggeredByLongPress);
            }
        }
    }

    @Override
    public void regsiterProjectionListener(ICarProjectionListener listener, int filter) {
        synchronized (this) {
            ListenerInfo info = (ListenerInfo) mAllListeners.getBinderInterface(listener);
            if (info == null) {
                info = new ListenerInfo(mAllListeners, listener, filter);
                mAllListeners.addBinderInterface(info);
            } else {
                info.setFilter(filter);
            }
        }
        updateCarInputServiceListeners();
    }

    @Override
    public void unregsiterProjectionListener(ICarProjectionListener listener) {
        synchronized (this) {
            mAllListeners.removeBinder(listener);
        }
        updateCarInputServiceListeners();
    }

    private void updateCarInputServiceListeners() {
        boolean listenShortPress = false;
        boolean listenLongPress = false;
        synchronized (this) {
            for (BinderInterfaceContainer.BinderInterface<ICarProjectionListener> listener :
                         mAllListeners.getInterfaces()) {
                ListenerInfo listenerInfo = (ListenerInfo) listener;
                listenShortPress |= listenerInfo.hasFilter(
                        CarProjectionManager.PROJECTION_VOICE_SEARCH);
                listenLongPress |= listenerInfo.hasFilter(
                        CarProjectionManager.PROJECTION_LONG_PRESS_VOICE_SEARCH);
            }
        }
        mCarInputService.setVoiceAssistantKeyListener(listenShortPress
                ? mVoiceAssistantKeyListener : null);
        mCarInputService.setLongVoiceAssistantKeyListener(listenLongPress
                ? mLongVoiceAssistantKeyListener : null);
    }

    @Override
    public void init() {
        // nothing to do
    }

    @Override
    public void release() {
        synchronized (this) {
            mAllListeners.clear();
        }
    }

    @Override
    public void onBinderDeath(
            BinderInterfaceContainer.BinderInterface<ICarProjectionListener> bInterface) {
        unregsiterProjectionListener(bInterface.binderInterface);
    }

    @Override
    public void dump(PrintWriter writer) {
        writer.println("**CarProjectionService**");
        synchronized (this) {
            for (BinderInterfaceContainer.BinderInterface<ICarProjectionListener> listener :
                         mAllListeners.getInterfaces()) {
                ListenerInfo listenerInfo = (ListenerInfo) listener;
                writer.println(listenerInfo.toString());
            }
        }
    }

    private void dispatchVoiceAssistantRequest(ICarProjectionListener listener,
            boolean fromLongPress) {
        try {
            listener.onVoiceAssistantRequest(fromLongPress);
        } catch (RemoteException e) {
        }
    }

    private static class ListenerHolder extends BinderInterfaceContainer<ICarProjectionListener> {
        private ListenerHolder(CarProjectionService service) {
            super(service);
        }
    }

    private static class ListenerInfo extends
            BinderInterfaceContainer.BinderInterface<ICarProjectionListener> {
        private int mFilter;

        private ListenerInfo(ListenerHolder holder, ICarProjectionListener binder, int filter) {
            super(holder, binder);
            this.mFilter = filter;
        }

        private synchronized int getFilter() {
            return mFilter;
        }

        private boolean hasFilter(int filter) {
            return (getFilter() & filter) != 0;
        }

        private synchronized void setFilter(int filter) {
            mFilter = filter;
        }

        @Override
        public String toString() {
            synchronized (this) {
                return "ListenerInfo{filter=" + Integer.toHexString(mFilter) + "}";
            }
        }
    }
}
