/*
 *  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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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.media.AudioManager;
import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
import java.util.ArrayList;
import java.util.List;
import org.appspot.apprtc.AppRTCBluetoothManager.State;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;

/**
 * Verifies basic behavior of the AppRTCBluetoothManager class. Note that the test object uses an
 * AppRTCAudioManager (injected in ctor), but a mocked version is used instead. Hence, the parts
 * "driven" by the AppRTC audio manager are not included in this test.
 */
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class BluetoothManagerTest {
  private static final String TAG = "BluetoothManagerTest";
  private static final String BLUETOOTH_TEST_DEVICE_NAME = "BluetoothTestDevice";

  private BroadcastReceiver bluetoothHeadsetStateReceiver;
  private BluetoothProfile.ServiceListener bluetoothServiceListener;
  private BluetoothHeadset mockedBluetoothHeadset;
  private BluetoothDevice mockedBluetoothDevice;
  private List<BluetoothDevice> mockedBluetoothDeviceList;
  private AppRTCBluetoothManager bluetoothManager;
  private AppRTCAudioManager mockedAppRtcAudioManager;
  private AudioManager mockedAudioManager;
  private Context context;

  @Before
  public void setUp() {
    ShadowLog.stream = System.out;
    context = ApplicationProvider.getApplicationContext();
    mockedAppRtcAudioManager = mock(AppRTCAudioManager.class);
    mockedAudioManager = mock(AudioManager.class);
    mockedBluetoothHeadset = mock(BluetoothHeadset.class);
    mockedBluetoothDevice = mock(BluetoothDevice.class);
    mockedBluetoothDeviceList = new ArrayList<BluetoothDevice>();

    // Simulate that bluetooth SCO audio is available by default.
    when(mockedAudioManager.isBluetoothScoAvailableOffCall()).thenReturn(true);

    // Create the test object and override protected methods for this test.
    bluetoothManager =
        new AppRTCBluetoothManager(context, mockedAppRtcAudioManager) {
          @Override
          protected AudioManager getAudioManager(Context context) {
            Log.d(TAG, "getAudioManager");
            return mockedAudioManager;
          }

          @Override
          protected void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            Log.d(TAG, "registerReceiver");
            if (filter.hasAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
                && filter.hasAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
              // Gives access to the real broadcast receiver so the test can use it.
              bluetoothHeadsetStateReceiver = receiver;
            }
          }

          @Override
          protected void unregisterReceiver(BroadcastReceiver receiver) {
            Log.d(TAG, "unregisterReceiver");
            if (receiver == bluetoothHeadsetStateReceiver) {
              bluetoothHeadsetStateReceiver = null;
            }
          }

          @Override
          protected boolean getBluetoothProfileProxy(
              Context context, BluetoothProfile.ServiceListener listener, int profile) {
            Log.d(TAG, "getBluetoothProfileProxy");
            if (profile == BluetoothProfile.HEADSET) {
              // Allows the test to access the real Bluetooth service listener object.
              bluetoothServiceListener = listener;
            }
            return true;
          }

          @Override
          protected boolean hasPermission(Context context, String permission) {
            Log.d(TAG, "hasPermission(" + permission + ")");
            // Ensure that the client asks for Bluetooth permission.
            return android.Manifest.permission.BLUETOOTH.equals(permission);
          }

          @Override
          protected void logBluetoothAdapterInfo(BluetoothAdapter localAdapter) {
            // Do nothing in tests. No need to mock BluetoothAdapter.
          }
        };
  }

  // Verify that Bluetooth service listener for headset profile is properly initialized.
  @Test
  public void testBluetoothServiceListenerInitialized() {
    bluetoothManager.start();
    assertNotNull(bluetoothServiceListener);
    verify(mockedAppRtcAudioManager, never()).updateAudioDeviceState();
  }

  // Verify that broadcast receivers for Bluetooth SCO audio state and Bluetooth headset state
  // are properly registered and unregistered.
  @Test
  public void testBluetoothBroadcastReceiversAreRegistered() {
    bluetoothManager.start();
    assertNotNull(bluetoothHeadsetStateReceiver);
    bluetoothManager.stop();
    assertNull(bluetoothHeadsetStateReceiver);
  }

  // Verify that the Bluetooth manager starts and stops with correct states.
  @Test
  public void testBluetoothDefaultStartStopStates() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    bluetoothManager.stop();
    assertEquals(State.UNINITIALIZED, bluetoothManager.getState());
  }

  // Verify correct state after receiving BluetoothServiceListener.onServiceConnected()
  // when no BT device is enabled.
  @Test
  public void testBluetoothServiceListenerConnectedWithNoHeadset() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    simulateBluetoothServiceConnectedWithNoConnectedHeadset();
    verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
  }

  // Verify correct state after receiving BluetoothServiceListener.onServiceConnected()
  // when one emulated (test) BT device is enabled. Android does not support more than
  // one connected BT headset.
  @Test
  public void testBluetoothServiceListenerConnectedWithHeadset() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState();
    assertEquals(State.HEADSET_AVAILABLE, bluetoothManager.getState());
  }

  // Verify correct state after receiving BluetoothProfile.ServiceListener.onServiceDisconnected().
  @Test
  public void testBluetoothServiceListenerDisconnected() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    simulateBluetoothServiceDisconnected();
    verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
  }

  // Verify correct state after BluetoothServiceListener.onServiceConnected() and
  // the intent indicating that the headset is actually connected. Both these callbacks
  // results in calls to updateAudioDeviceState() on the AppRTC audio manager.
  // No BT SCO is enabled here to keep the test limited.
  @Test
  public void testBluetoothHeadsetConnected() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    simulateBluetoothHeadsetConnected();
    verify(mockedAppRtcAudioManager, times(2)).updateAudioDeviceState();
    assertEquals(State.HEADSET_AVAILABLE, bluetoothManager.getState());
  }

  // Verify correct state sequence for a case when a BT headset is available,
  // followed by BT SCO audio being enabled and then stopped.
  @Test
  @Ignore("https://issues.webrtc.org/481918423")
  public void testBluetoothScoAudioStartAndStop() {
    bluetoothManager.start();
    assertEquals(State.HEADSET_UNAVAILABLE, bluetoothManager.getState());
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    assertEquals(State.HEADSET_AVAILABLE, bluetoothManager.getState());
    bluetoothManager.startScoAudio();
    assertEquals(State.SCO_CONNECTING, bluetoothManager.getState());
    simulateBluetoothScoConnectionConnected();
    assertEquals(State.SCO_CONNECTED, bluetoothManager.getState());
    bluetoothManager.stopScoAudio();
    simulateBluetoothScoConnectionDisconnected();
    assertEquals(State.SCO_DISCONNECTING, bluetoothManager.getState());
    bluetoothManager.stop();
    assertEquals(State.UNINITIALIZED, bluetoothManager.getState());
    verify(mockedAppRtcAudioManager, times(3)).updateAudioDeviceState();
  }

  /** Private helper methods. */
  private void simulateBluetoothServiceConnectedWithNoConnectedHeadset() {
    mockedBluetoothDeviceList.clear();
    when(mockedBluetoothHeadset.getConnectedDevices()).thenReturn(mockedBluetoothDeviceList);
    bluetoothServiceListener.onServiceConnected(BluetoothProfile.HEADSET, mockedBluetoothHeadset);
    // In real life, the AppRTC audio manager makes this call.
    bluetoothManager.updateDevice();
  }

  private void simulateBluetoothServiceConnectedWithConnectedHeadset() {
    mockedBluetoothDeviceList.clear();
    mockedBluetoothDeviceList.add(mockedBluetoothDevice);
    when(mockedBluetoothHeadset.getConnectedDevices()).thenReturn(mockedBluetoothDeviceList);
    when(mockedBluetoothDevice.getName()).thenReturn(BLUETOOTH_TEST_DEVICE_NAME);
    bluetoothServiceListener.onServiceConnected(BluetoothProfile.HEADSET, mockedBluetoothHeadset);
    // In real life, the AppRTC audio manager makes this call.
    bluetoothManager.updateDevice();
  }

  private void simulateBluetoothServiceDisconnected() {
    bluetoothServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
  }

  private void simulateBluetoothHeadsetConnected() {
    Intent intent = new Intent();
    intent.setAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
    intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_CONNECTED);
    bluetoothHeadsetStateReceiver.onReceive(context, intent);
  }

  private void simulateBluetoothScoConnectionConnected() {
    Intent intent = new Intent();
    intent.setAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_CONNECTED);
    bluetoothHeadsetStateReceiver.onReceive(context, intent);
  }

  private void simulateBluetoothScoConnectionDisconnected() {
    Intent intent = new Intent();
    intent.setAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
    intent.putExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
    bluetoothHeadsetStateReceiver.onReceive(context, intent);
  }
}
