/*
 *  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.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doCallRealMethod;
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 java.util.LinkedList;
import java.util.List;
import org.appspot.apprtc.AppRTCBluetoothManager.State;
import org.chromium.testing.local.LocalRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
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(LocalRobolectricTestRunner.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 = ShadowApplication.getInstance().getApplicationContext();
    mockedAppRtcAudioManager = mock(AppRTCAudioManager.class);
    mockedAudioManager = mock(AudioManager.class);
    mockedBluetoothHeadset = mock(BluetoothHeadset.class);
    mockedBluetoothDevice = mock(BluetoothDevice.class);
    mockedBluetoothDeviceList = new LinkedList<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 (permission == android.Manifest.permission.BLUETOOTH);
      }

      @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(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE);
    bluetoothManager.stop();
    assertEquals(bluetoothManager.getState(), State.UNINITIALIZED);
  }

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

  // 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(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE);
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    verify(mockedAppRtcAudioManager, times(1)).updateAudioDeviceState();
    assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE);
  }

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

  // 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(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE);
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    simulateBluetoothHeadsetConnected();
    verify(mockedAppRtcAudioManager, times(2)).updateAudioDeviceState();
    assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE);
  }

  // Verify correct state sequence for a case when a BT headset is available,
  // followed by BT SCO audio being enabled and then stopped.
  @Test
  public void testBluetoothScoAudioStartAndStop() {
    bluetoothManager.start();
    assertEquals(bluetoothManager.getState(), State.HEADSET_UNAVAILABLE);
    simulateBluetoothServiceConnectedWithConnectedHeadset();
    assertEquals(bluetoothManager.getState(), State.HEADSET_AVAILABLE);
    bluetoothManager.startScoAudio();
    assertEquals(bluetoothManager.getState(), State.SCO_CONNECTING);
    simulateBluetoothScoConnectionConnected();
    assertEquals(bluetoothManager.getState(), State.SCO_CONNECTED);
    bluetoothManager.stopScoAudio();
    simulateBluetoothScoConnectionDisconnected();
    assertEquals(bluetoothManager.getState(), State.SCO_DISCONNECTING);
    bluetoothManager.stop();
    assertEquals(bluetoothManager.getState(), State.UNINITIALIZED);
    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);
  }
}
