/*
 *  Copyright 2016 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.appspot.apprtc;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.util.Log;
import java.util.List;
import java.util.Set;
import org.appspot.apprtc.util.AppRTCUtils;
import org.webrtc.ThreadUtils;

/**
 * AppRTCProximitySensor manages functions related to Bluetoth devices in the
 * AppRTC demo.
 */
public class AppRTCBluetoothManager {
  private static final String TAG = "AppRTCBluetoothManager";

  // Timeout interval for starting or stopping audio to a Bluetooth SCO device.
  private static final int BLUETOOTH_SCO_TIMEOUT_MS = 4000;
  // Maximum number of SCO connection attempts.
  private static final int MAX_SCO_CONNECTION_ATTEMPTS = 2;

  // Bluetooth connection state.
  public enum State {
    // Bluetooth is not available; no adapter or Bluetooth is off.
    UNINITIALIZED,
    // Bluetooth error happened when trying to start Bluetooth.
    ERROR,
    // Bluetooth proxy object for the Headset profile exists, but no connected headset devices,
    // SCO is not started or disconnected.
    HEADSET_UNAVAILABLE,
    // Bluetooth proxy object for the Headset profile connected, connected Bluetooth headset
    // present, but SCO is not started or disconnected.
    HEADSET_AVAILABLE,
    // Bluetooth audio SCO connection with remote device is closing.
    SCO_DISCONNECTING,
    // Bluetooth audio SCO connection with remote device is initiated.
    SCO_CONNECTING,
    // Bluetooth audio SCO connection with remote device is established.
    SCO_CONNECTED
  }

  private final Context apprtcContext;
  private final AppRTCAudioManager apprtcAudioManager;
  private final AudioManager audioManager;
  private final Handler handler;

  int scoConnectionAttempts;
  private State bluetoothState;
  private final BluetoothProfile.ServiceListener bluetoothServiceListener;
  private BluetoothAdapter bluetoothAdapter;
  private BluetoothHeadset bluetoothHeadset;
  private BluetoothDevice bluetoothDevice;
  private final BroadcastReceiver bluetoothHeadsetReceiver;

  // Runs when the Bluetooth timeout expires. We use that timeout after calling
  // startScoAudio() or stopScoAudio() because we're not guaranteed to get a
  // callback after those calls.
  private final Runnable bluetoothTimeoutRunnable = new Runnable() {
    @Override
    public void run() {
      bluetoothTimeout();
    }
  };

  /**
   * Implementation of an interface that notifies BluetoothProfile IPC clients when they have been
   * connected to or disconnected from the service.
   */
  private class BluetoothServiceListener implements BluetoothProfile.ServiceListener {
    @Override
    // Called to notify the client when the proxy object has been connected to the service.
    // Once we have the profile proxy object, we can use it to monitor the state of the
    // connection and perform other operations that are relevant to the headset profile.
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
      if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
        return;
      }
      Log.d(TAG, "BluetoothServiceListener.onServiceConnected: BT state=" + bluetoothState);
      // Android only supports one connected Bluetooth Headset at a time.
      bluetoothHeadset = (BluetoothHeadset) proxy;
      updateAudioDeviceState();
      Log.d(TAG, "onServiceConnected done: BT state=" + bluetoothState);
    }

    @Override
    /** Notifies the client when the proxy object has been disconnected from the service. */
    public void onServiceDisconnected(int profile) {
      if (profile != BluetoothProfile.HEADSET || bluetoothState == State.UNINITIALIZED) {
        return;
      }
      Log.d(TAG, "BluetoothServiceListener.onServiceDisconnected: BT state=" + bluetoothState);
      stopScoAudio();
      bluetoothHeadset = null;
      bluetoothDevice = null;
      bluetoothState = State.HEADSET_UNAVAILABLE;
      updateAudioDeviceState();
      Log.d(TAG, "onServiceDisconnected done: BT state=" + bluetoothState);
    }
  }

  // Intent broadcast receiver which handles changes in Bluetooth device availability.
  // Detects headset changes and Bluetooth SCO state changes.
  private class BluetoothHeadsetBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
      if (bluetoothState == State.UNINITIALIZED) {
        return;
      }
      final String action = intent.getAction();
      // Change in connection state of the Headset profile. Note that the
      // change does not tell us anything about whether we're streaming
      // audio to BT over SCO. Typically received when user turns on a BT
      // headset while audio is active using another audio device.
      if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
        final int state =
            intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED);
        Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: "
                + "a=ACTION_CONNECTION_STATE_CHANGED, "
                + "s=" + stateToString(state) + ", "
                + "sb=" + isInitialStickyBroadcast() + ", "
                + "BT state: " + bluetoothState);
        if (state == BluetoothHeadset.STATE_CONNECTED) {
          scoConnectionAttempts = 0;
          updateAudioDeviceState();
        } else if (state == BluetoothHeadset.STATE_CONNECTING) {
          // No action needed.
        } else if (state == BluetoothHeadset.STATE_DISCONNECTING) {
          // No action needed.
        } else if (state == BluetoothHeadset.STATE_DISCONNECTED) {
          // Bluetooth is probably powered off during the call.
          stopScoAudio();
          updateAudioDeviceState();
        }
        // Change in the audio (SCO) connection state of the Headset profile.
        // Typically received after call to startScoAudio() has finalized.
      } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
        final int state = intent.getIntExtra(
            BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
        Log.d(TAG, "BluetoothHeadsetBroadcastReceiver.onReceive: "
                + "a=ACTION_AUDIO_STATE_CHANGED, "
                + "s=" + stateToString(state) + ", "
                + "sb=" + isInitialStickyBroadcast() + ", "
                + "BT state: " + bluetoothState);
        if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
          cancelTimer();
          if (bluetoothState == State.SCO_CONNECTING) {
            Log.d(TAG, "+++ Bluetooth audio SCO is now connected");
            bluetoothState = State.SCO_CONNECTED;
            scoConnectionAttempts = 0;
            updateAudioDeviceState();
          } else {
            Log.w(TAG, "Unexpected state BluetoothHeadset.STATE_AUDIO_CONNECTED");
          }
        } else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) {
          Log.d(TAG, "+++ Bluetooth audio SCO is now connecting...");
        } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
          Log.d(TAG, "+++ Bluetooth audio SCO is now disconnected");
          if (isInitialStickyBroadcast()) {
            Log.d(TAG, "Ignore STATE_AUDIO_DISCONNECTED initial sticky broadcast.");
            return;
          }
          updateAudioDeviceState();
        }
      }
      Log.d(TAG, "onReceive done: BT state=" + bluetoothState);
    }
  }

  /** Construction. */
  static AppRTCBluetoothManager create(Context context, AppRTCAudioManager audioManager) {
    Log.d(TAG, "create" + AppRTCUtils.getThreadInfo());
    return new AppRTCBluetoothManager(context, audioManager);
  }

  protected AppRTCBluetoothManager(Context context, AppRTCAudioManager audioManager) {
    Log.d(TAG, "ctor");
    ThreadUtils.checkIsOnMainThread();
    apprtcContext = context;
    apprtcAudioManager = audioManager;
    this.audioManager = getAudioManager(context);
    bluetoothState = State.UNINITIALIZED;
    bluetoothServiceListener = new BluetoothServiceListener();
    bluetoothHeadsetReceiver = new BluetoothHeadsetBroadcastReceiver();
    handler = new Handler(Looper.getMainLooper());
  }

  /** Returns the internal state. */
  public State getState() {
    ThreadUtils.checkIsOnMainThread();
    return bluetoothState;
  }

  /**
   * Activates components required to detect Bluetooth devices and to enable
   * BT SCO (audio is routed via BT SCO) for the headset profile. The end
   * state will be HEADSET_UNAVAILABLE but a state machine has started which
   * will start a state change sequence where the final outcome depends on
   * if/when the BT headset is enabled.
   * Example of state change sequence when start() is called while BT device
   * is connected and enabled:
   *   UNINITIALIZED --> HEADSET_UNAVAILABLE --> HEADSET_AVAILABLE -->
   *   SCO_CONNECTING --> SCO_CONNECTED <==> audio is now routed via BT SCO.
   * Note that the AppRTCAudioManager is also involved in driving this state
   * change.
   */
  public void start() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "start");
    if (!hasPermission(apprtcContext, android.Manifest.permission.BLUETOOTH)) {
      Log.w(TAG, "Process (pid=" + Process.myPid() + ") lacks BLUETOOTH permission");
      return;
    }
    if (bluetoothState != State.UNINITIALIZED) {
      Log.w(TAG, "Invalid BT state");
      return;
    }
    bluetoothHeadset = null;
    bluetoothDevice = null;
    scoConnectionAttempts = 0;
    // Get a handle to the default local Bluetooth adapter.
    bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
      Log.w(TAG, "Device does not support Bluetooth");
      return;
    }
    // Ensure that the device supports use of BT SCO audio for off call use cases.
    if (!audioManager.isBluetoothScoAvailableOffCall()) {
      Log.e(TAG, "Bluetooth SCO audio is not available off call");
      return;
    }
    logBluetoothAdapterInfo(bluetoothAdapter);
    // Establish a connection to the HEADSET profile (includes both Bluetooth Headset and
    // Hands-Free) proxy object and install a listener.
    if (!getBluetoothProfileProxy(
            apprtcContext, bluetoothServiceListener, BluetoothProfile.HEADSET)) {
      Log.e(TAG, "BluetoothAdapter.getProfileProxy(HEADSET) failed");
      return;
    }
    // Register receivers for BluetoothHeadset change notifications.
    IntentFilter bluetoothHeadsetFilter = new IntentFilter();
    // Register receiver for change in connection state of the Headset profile.
    bluetoothHeadsetFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
    // Register receiver for change in audio connection state of the Headset profile.
    bluetoothHeadsetFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    registerReceiver(bluetoothHeadsetReceiver, bluetoothHeadsetFilter);
    Log.d(TAG, "HEADSET profile state: "
            + stateToString(bluetoothAdapter.getProfileConnectionState(BluetoothProfile.HEADSET)));
    Log.d(TAG, "Bluetooth proxy for headset profile has started");
    bluetoothState = State.HEADSET_UNAVAILABLE;
    Log.d(TAG, "start done: BT state=" + bluetoothState);
  }

  /** Stops and closes all components related to Bluetooth audio. */
  public void stop() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "stop: BT state=" + bluetoothState);
    if (bluetoothAdapter == null) {
      return;
    }
    // Stop BT SCO connection with remote device if needed.
    stopScoAudio();
    // Close down remaining BT resources.
    if (bluetoothState == State.UNINITIALIZED) {
      return;
    }
    unregisterReceiver(bluetoothHeadsetReceiver);
    cancelTimer();
    if (bluetoothHeadset != null) {
      bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, bluetoothHeadset);
      bluetoothHeadset = null;
    }
    bluetoothAdapter = null;
    bluetoothDevice = null;
    bluetoothState = State.UNINITIALIZED;
    Log.d(TAG, "stop done: BT state=" + bluetoothState);
  }

  /**
   * Starts Bluetooth SCO connection with remote device.
   * Note that the phone application always has the priority on the usage of the SCO connection
   * for telephony. If this method is called while the phone is in call it will be ignored.
   * Similarly, if a call is received or sent while an application is using the SCO connection,
   * the connection will be lost for the application and NOT returned automatically when the call
   * ends. Also note that: up to and including API version JELLY_BEAN_MR1, this method initiates a
   * virtual voice call to the Bluetooth headset. After API version JELLY_BEAN_MR2 only a raw SCO
   * audio connection is established.
   * TODO(henrika): should we add support for virtual voice call to BT headset also for JBMR2 and
   * higher. It might be required to initiates a virtual voice call since many devices do not
   * accept SCO audio without a "call".
   */
  public boolean startScoAudio() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "startSco: BT state=" + bluetoothState + ", "
            + "attempts: " + scoConnectionAttempts + ", "
            + "SCO is on: " + isScoOn());
    if (scoConnectionAttempts >= MAX_SCO_CONNECTION_ATTEMPTS) {
      Log.e(TAG, "BT SCO connection fails - no more attempts");
      return false;
    }
    if (bluetoothState != State.HEADSET_AVAILABLE) {
      Log.e(TAG, "BT SCO connection fails - no headset available");
      return false;
    }
    // Start BT SCO channel and wait for ACTION_AUDIO_STATE_CHANGED.
    Log.d(TAG, "Starting Bluetooth SCO and waits for ACTION_AUDIO_STATE_CHANGED...");
    // The SCO connection establishment can take several seconds, hence we cannot rely on the
    // connection to be available when the method returns but instead register to receive the
    // intent ACTION_SCO_AUDIO_STATE_UPDATED and wait for the state to be SCO_AUDIO_STATE_CONNECTED.
    bluetoothState = State.SCO_CONNECTING;
    audioManager.startBluetoothSco();
    audioManager.setBluetoothScoOn(true);
    scoConnectionAttempts++;
    startTimer();
    Log.d(TAG, "startScoAudio done: BT state=" + bluetoothState + ", "
            + "SCO is on: " + isScoOn());
    return true;
  }

  /** Stops Bluetooth SCO connection with remote device. */
  public void stopScoAudio() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "stopScoAudio: BT state=" + bluetoothState + ", "
            + "SCO is on: " + isScoOn());
    if (bluetoothState != State.SCO_CONNECTING && bluetoothState != State.SCO_CONNECTED) {
      return;
    }
    cancelTimer();
    audioManager.stopBluetoothSco();
    audioManager.setBluetoothScoOn(false);
    bluetoothState = State.SCO_DISCONNECTING;
    Log.d(TAG, "stopScoAudio done: BT state=" + bluetoothState + ", "
            + "SCO is on: " + isScoOn());
  }

  /**
   * Use the BluetoothHeadset proxy object (controls the Bluetooth Headset
   * Service via IPC) to update the list of connected devices for the HEADSET
   * profile. The internal state will change to HEADSET_UNAVAILABLE or to
   * HEADSET_AVAILABLE and |bluetoothDevice| will be mapped to the connected
   * device if available.
   */
  public void updateDevice() {
    if (bluetoothState == State.UNINITIALIZED || bluetoothHeadset == null) {
      return;
    }
    Log.d(TAG, "updateDevice");
    // Get connected devices for the headset profile. Returns the set of
    // devices which are in state STATE_CONNECTED. The BluetoothDevice class
    // is just a thin wrapper for a Bluetooth hardware address.
    List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
    if (devices.isEmpty()) {
      bluetoothDevice = null;
      bluetoothState = State.HEADSET_UNAVAILABLE;
      Log.d(TAG, "No connected bluetooth headset");
    } else {
      // Always use first device in list. Android only supports one device.
      bluetoothDevice = devices.get(0);
      bluetoothState = State.HEADSET_AVAILABLE;
      Log.d(TAG, "Connected bluetooth headset: "
              + "name=" + bluetoothDevice.getName() + ", "
              + "state=" + stateToString(bluetoothHeadset.getConnectionState(bluetoothDevice))
              + ", SCO audio=" + bluetoothHeadset.isAudioConnected(bluetoothDevice));
    }
    Log.d(TAG, "updateDevice done: BT state=" + bluetoothState);
  }

  /**
   * Stubs for test mocks.
   */
  protected AudioManager getAudioManager(Context context) {
    return (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
  }

  protected void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    apprtcContext.registerReceiver(receiver, filter);
  }

  protected void unregisterReceiver(BroadcastReceiver receiver) {
    apprtcContext.unregisterReceiver(receiver);
  }

  protected boolean getBluetoothProfileProxy(
      Context context, BluetoothProfile.ServiceListener listener, int profile) {
    return bluetoothAdapter.getProfileProxy(context, listener, profile);
  }

  protected boolean hasPermission(Context context, String permission) {
    return apprtcContext.checkPermission(permission, Process.myPid(), Process.myUid())
        == PackageManager.PERMISSION_GRANTED;
  }

  /** Logs the state of the local Bluetooth adapter. */
  @SuppressLint("HardwareIds")
  protected void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) {
    Log.d(TAG, "BluetoothAdapter: "
            + "enabled=" + localAdapter.isEnabled() + ", "
            + "state=" + stateToString(localAdapter.getState()) + ", "
            + "name=" + localAdapter.getName() + ", "
            + "address=" + localAdapter.getAddress());
    // Log the set of BluetoothDevice objects that are bonded (paired) to the local adapter.
    Set<BluetoothDevice> pairedDevices = localAdapter.getBondedDevices();
    if (!pairedDevices.isEmpty()) {
      Log.d(TAG, "paired devices:");
      for (BluetoothDevice device : pairedDevices) {
        Log.d(TAG, " name=" + device.getName() + ", address=" + device.getAddress());
      }
    }
  }

  /** Ensures that the audio manager updates its list of available audio devices. */
  private void updateAudioDeviceState() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "updateAudioDeviceState");
    apprtcAudioManager.updateAudioDeviceState();
  }

  /** Starts timer which times out after BLUETOOTH_SCO_TIMEOUT_MS milliseconds. */
  private void startTimer() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "startTimer");
    handler.postDelayed(bluetoothTimeoutRunnable, BLUETOOTH_SCO_TIMEOUT_MS);
  }

  /** Cancels any outstanding timer tasks. */
  private void cancelTimer() {
    ThreadUtils.checkIsOnMainThread();
    Log.d(TAG, "cancelTimer");
    handler.removeCallbacks(bluetoothTimeoutRunnable);
  }

  /**
   * Called when start of the BT SCO channel takes too long time. Usually
   * happens when the BT device has been turned on during an ongoing call.
   */
  private void bluetoothTimeout() {
    ThreadUtils.checkIsOnMainThread();
    if (bluetoothState == State.UNINITIALIZED || bluetoothHeadset == null) {
      return;
    }
    Log.d(TAG, "bluetoothTimeout: BT state=" + bluetoothState + ", "
            + "attempts: " + scoConnectionAttempts + ", "
            + "SCO is on: " + isScoOn());
    if (bluetoothState != State.SCO_CONNECTING) {
      return;
    }
    // Bluetooth SCO should be connecting; check the latest result.
    boolean scoConnected = false;
    List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
    if (devices.size() > 0) {
      bluetoothDevice = devices.get(0);
      if (bluetoothHeadset.isAudioConnected(bluetoothDevice)) {
        Log.d(TAG, "SCO connected with " + bluetoothDevice.getName());
        scoConnected = true;
      } else {
        Log.d(TAG, "SCO is not connected with " + bluetoothDevice.getName());
      }
    }
    if (scoConnected) {
      // We thought BT had timed out, but it's actually on; updating state.
      bluetoothState = State.SCO_CONNECTED;
      scoConnectionAttempts = 0;
    } else {
      // Give up and "cancel" our request by calling stopBluetoothSco().
      Log.w(TAG, "BT failed to connect after timeout");
      stopScoAudio();
    }
    updateAudioDeviceState();
    Log.d(TAG, "bluetoothTimeout done: BT state=" + bluetoothState);
  }

  /** Checks whether audio uses Bluetooth SCO. */
  private boolean isScoOn() {
    return audioManager.isBluetoothScoOn();
  }

  /** Converts BluetoothAdapter states into local string representations. */
  private String stateToString(int state) {
    switch (state) {
      case BluetoothAdapter.STATE_DISCONNECTED:
        return "DISCONNECTED";
      case BluetoothAdapter.STATE_CONNECTED:
        return "CONNECTED";
      case BluetoothAdapter.STATE_CONNECTING:
        return "CONNECTING";
      case BluetoothAdapter.STATE_DISCONNECTING:
        return "DISCONNECTING";
      case BluetoothAdapter.STATE_OFF:
        return "OFF";
      case BluetoothAdapter.STATE_ON:
        return "ON";
      case BluetoothAdapter.STATE_TURNING_OFF:
        // Indicates the local Bluetooth adapter is turning off. Local clients should immediately
        // attempt graceful disconnection of any remote links.
        return "TURNING_OFF";
      case BluetoothAdapter.STATE_TURNING_ON:
        // Indicates the local Bluetooth adapter is turning on. However local clients should wait
        // for STATE_ON before attempting to use the adapter.
        return  "TURNING_ON";
      default:
        return "INVALID";
    }
  }
}
