/*
 * Copyright 2017 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.bluetooth.hfp;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.IBluetoothHeadsetPhone;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.AudioManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.util.List;

/**
 * Defines system calls that is used by state machine/service to either send or receive
 * messages from the Android System.
 */
@VisibleForTesting
public class HeadsetSystemInterface {
    private static final String TAG = HeadsetSystemInterface.class.getSimpleName();
    private static final boolean DBG = false;

    private final HeadsetService mHeadsetService;
    private final AudioManager mAudioManager;
    private final HeadsetPhoneState mHeadsetPhoneState;
    private PowerManager.WakeLock mVoiceRecognitionWakeLock;
    private volatile IBluetoothHeadsetPhone mPhoneProxy;
    private final ServiceConnection mPhoneProxyConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            if (DBG) {
                Log.d(TAG, "Proxy object connected");
            }
            synchronized (HeadsetSystemInterface.this) {
                mPhoneProxy = IBluetoothHeadsetPhone.Stub.asInterface(service);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName className) {
            if (DBG) {
                Log.d(TAG, "Proxy object disconnected");
            }
            synchronized (HeadsetSystemInterface.this) {
                mPhoneProxy = null;
            }
        }
    };

    HeadsetSystemInterface(HeadsetService headsetService) {
        if (headsetService == null) {
            Log.wtf(TAG, "HeadsetService parameter is null");
        }
        mHeadsetService = headsetService;
        mAudioManager = (AudioManager) mHeadsetService.getSystemService(Context.AUDIO_SERVICE);
        PowerManager powerManager =
                (PowerManager) mHeadsetService.getSystemService(Context.POWER_SERVICE);
        mVoiceRecognitionWakeLock =
                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG + ":VoiceRecognition");
        mVoiceRecognitionWakeLock.setReferenceCounted(false);
        mHeadsetPhoneState = new HeadsetPhoneState(mHeadsetService);
    }

    /**
     * Initialize this system interface
     */
    public synchronized void init() {
        // Bind to Telecom phone proxy service
        Intent intent = new Intent(IBluetoothHeadsetPhone.class.getName());
        intent.setComponent(resolveSystemService(mHeadsetService.getPackageManager(), 0, intent));
        if (intent.getComponent() == null || !mHeadsetService.bindService(intent,
                mPhoneProxyConnection, 0)) {
            // Crash the stack if cannot bind to Telecom
            Log.wtf(TAG, "Could not bind to IBluetoothHeadsetPhone Service, intent=" + intent);
        }
    }

    /**
     * Special function for use by the system to resolve service
     * intents to system apps.  Throws an exception if there are
     * multiple potential matches to the Intent.  Returns null if
     * there are no matches.
     */
    private @Nullable ComponentName resolveSystemService(@NonNull PackageManager pm,
            @PackageManager.ComponentInfoFlags int flags, Intent intent) {
        if (intent.getComponent() != null) {
            return intent.getComponent();
        }

        List<ResolveInfo> results = pm.queryIntentServices(intent, flags);
        if (results == null) {
            return null;
        }
        ComponentName comp = null;
        for (int i = 0; i < results.size(); i++) {
            ResolveInfo ri = results.get(i);
            if ((ri.serviceInfo.applicationInfo.flags& ApplicationInfo.FLAG_SYSTEM) == 0) {
                continue;
            }
            ComponentName foundComp = new ComponentName(ri.serviceInfo.applicationInfo.packageName,
                    ri.serviceInfo.name);
            if (comp != null) {
                throw new IllegalStateException("Multiple system services handle " + this
                        + ": " + comp + ", " + foundComp);
            }
            comp = foundComp;
        }
        return comp;
    }

    /**
     * Stop this system interface
     */
    public synchronized void stop() {
        if (mPhoneProxy != null) {
            if (DBG) {
                Log.d(TAG, "Unbinding phone proxy");
            }
            mPhoneProxy = null;
            // Synchronization should make sure unbind can be successful
            mHeadsetService.unbindService(mPhoneProxyConnection);
        }
        mHeadsetPhoneState.cleanup();
    }

    /**
     * Get audio manager. Most audio manager oprations are pass through and therefore are not
     * individually managed by this class
     *
     * @return audio manager for setting audio parameters
     */
    @VisibleForTesting
    public AudioManager getAudioManager() {
        return mAudioManager;
    }

    /**
     * Get wake lock for voice recognition
     *
     * @return wake lock for voice recognition
     */
    @VisibleForTesting
    public PowerManager.WakeLock getVoiceRecognitionWakeLock() {
        return mVoiceRecognitionWakeLock;
    }

    /**
     * Get HeadsetPhoneState instance to interact with Telephony service
     *
     * @return HeadsetPhoneState interface to interact with Telephony service
     */
    @VisibleForTesting
    public HeadsetPhoneState getHeadsetPhoneState() {
        return mHeadsetPhoneState;
    }

    /**
     * Answer the current incoming call in Telecom service
     *
     * @param device the Bluetooth device used for answering this call
     */
    @VisibleForTesting
    public void answerCall(BluetoothDevice device) {
        if (device == null) {
            Log.w(TAG, "answerCall device is null");
            return;
        }

        if (mPhoneProxy != null) {
            try {
                mHeadsetService.setActiveDevice(device);
                mPhoneProxy.answerCall();
            } catch (RemoteException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
            }
        } else {
            Log.e(TAG, "Handsfree phone proxy null for answering call");
        }
    }

    /**
     * Hangup the current call, could either be Telecom call or virtual call
     *
     * @param device the Bluetooth device used for hanging up this call
     */
    @VisibleForTesting
    public void hangupCall(BluetoothDevice device) {
        if (device == null) {
            Log.w(TAG, "hangupCall device is null");
            return;
        }
        // Close the virtual call if active. Virtual call should be
        // terminated for CHUP callback event
        if (mHeadsetService.isVirtualCallStarted()) {
            mHeadsetService.stopScoUsingVirtualVoiceCall();
        } else {
            if (mPhoneProxy != null) {
                try {
                    mPhoneProxy.hangupCall();
                } catch (RemoteException e) {
                    Log.e(TAG, Log.getStackTraceString(new Throwable()));
                }
            } else {
                Log.e(TAG, "Handsfree phone proxy null for hanging up call");
            }
        }
    }

    /**
     * Instructs Telecom to play the specified DTMF tone for the current foreground call
     *
     * @param dtmf dtmf code
     * @param device the Bluetooth device that sent this code
     */
    @VisibleForTesting
    public boolean sendDtmf(int dtmf, BluetoothDevice device) {
        if (device == null) {
            Log.w(TAG, "sendDtmf device is null");
            return false;
        }
        if (mPhoneProxy != null) {
            try {
                return mPhoneProxy.sendDtmf(dtmf);
            } catch (RemoteException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
            }
        } else {
            Log.e(TAG, "Handsfree phone proxy null for sending DTMF");
        }
        return false;
    }

    /**
     * Instructs Telecom hold an incoming call
     *
     * @param chld index of the call to hold
     */
    @VisibleForTesting
    public boolean processChld(int chld) {
        if (mPhoneProxy != null) {
            try {
                return mPhoneProxy.processChld(chld);
            } catch (RemoteException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
            }
        } else {
            Log.e(TAG, "Handsfree phone proxy null for sending DTMF");
        }
        return false;
    }

    /**
     * Get the the alphabetic name of current registered operator.
     *
     * @return null on error, empty string if not available
     */
    @VisibleForTesting
    public String getNetworkOperator() {
        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
        if (phoneProxy == null) {
            Log.e(TAG, "getNetworkOperator() failed: mPhoneProxy is null");
            return null;
        }
        try {
            // Should never return null
            return mPhoneProxy.getNetworkOperator();
        } catch (RemoteException exception) {
            Log.e(TAG, "getNetworkOperator() failed: " + exception.getMessage());
            exception.printStackTrace();
            return null;
        }
    }

    /**
     * Get the phone number of this device
     *
     * @return null if unavailable
     */
    @VisibleForTesting
    public String getSubscriberNumber() {
        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
        if (phoneProxy == null) {
            Log.e(TAG, "getSubscriberNumber() failed: mPhoneProxy is null");
            return null;
        }
        try {
            return mPhoneProxy.getSubscriberNumber();
        } catch (RemoteException exception) {
            Log.e(TAG, "getSubscriberNumber() failed: " + exception.getMessage());
            exception.printStackTrace();
            return null;
        }
    }


    /**
     * Ask the Telecomm service to list current list of calls through CLCC response
     * {@link BluetoothHeadset#clccResponse(int, int, int, int, boolean, String, int)}
     *
     * @return
     */
    @VisibleForTesting
    public boolean listCurrentCalls() {
        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
        if (phoneProxy == null) {
            Log.e(TAG, "listCurrentCalls() failed: mPhoneProxy is null");
            return false;
        }
        try {
            return mPhoneProxy.listCurrentCalls();
        } catch (RemoteException exception) {
            Log.e(TAG, "listCurrentCalls() failed: " + exception.getMessage());
            exception.printStackTrace();
            return false;
        }
    }

    /**
     * Request Telecom service to send an update of the current call state to the headset service
     * through {@link BluetoothHeadset#phoneStateChanged(int, int, int, String, int)}
     */
    @VisibleForTesting
    public void queryPhoneState() {
        final IBluetoothHeadsetPhone phoneProxy = mPhoneProxy;
        if (phoneProxy != null) {
            try {
                mPhoneProxy.queryPhoneState();
            } catch (RemoteException e) {
                Log.e(TAG, Log.getStackTraceString(new Throwable()));
            }
        } else {
            Log.e(TAG, "Handsfree phone proxy null for query phone state");
        }
    }

    /**
     * Check if we are currently in a phone call
     *
     * @return True iff we are in a phone call
     */
    @VisibleForTesting
    public boolean isInCall() {
        return ((mHeadsetPhoneState.getNumActiveCall() > 0) || (mHeadsetPhoneState.getNumHeldCall()
                > 0) || ((mHeadsetPhoneState.getCallState() != HeadsetHalConstants.CALL_STATE_IDLE)
                && (mHeadsetPhoneState.getCallState() != HeadsetHalConstants.CALL_STATE_INCOMING)));
    }

    /**
     * Check if there is currently an incoming call
     *
     * @return True iff there is an incoming call
     */
    @VisibleForTesting
    public boolean isRinging() {
        return mHeadsetPhoneState.getCallState() == HeadsetHalConstants.CALL_STATE_INCOMING;
    }

    /**
     * Check if call status is idle
     *
     * @return true if call state is neither ringing nor in call
     */
    @VisibleForTesting
    public boolean isCallIdle() {
        return !isInCall() && !isRinging();
    }

    /**
     * Activate voice recognition on Android system
     *
     * @return true if activation succeeds, caller should wait for
     * {@link BluetoothHeadset#startVoiceRecognition(BluetoothDevice)} callback that will then
     * trigger {@link HeadsetService#startVoiceRecognition(BluetoothDevice)}, false if failed to
     * activate
     */
    @VisibleForTesting
    public boolean activateVoiceRecognition() {
        Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            mHeadsetService.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.e(TAG, "activateVoiceRecognition, failed due to activity not found for " + intent);
            return false;
        }
        return true;
    }

    /**
     * Deactivate voice recognition on Android system
     *
     * @return true if activation succeeds, caller should wait for
     * {@link BluetoothHeadset#stopVoiceRecognition(BluetoothDevice)} callback that will then
     * trigger {@link HeadsetService#stopVoiceRecognition(BluetoothDevice)}, false if failed to
     * activate
     */
    @VisibleForTesting
    public boolean deactivateVoiceRecognition() {
        // TODO: need a method to deactivate voice recognition on Android
        return true;
    }

}
