/*
 * Copyright (C) 2019 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.connecteddevice.ble;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockitoSession;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.annotation.NonNull;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.car.encryptionrunner.EncryptionRunnerFactory;
import android.car.encryptionrunner.Key;
import android.os.ParcelUuid;

import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.car.connecteddevice.AssociationCallback;
import com.android.car.connecteddevice.model.AssociatedDevice;
import com.android.car.connecteddevice.storage.ConnectedDeviceStorage;
import com.android.car.connecteddevice.util.ByteUtils;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;

import java.util.UUID;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public class CarBlePeripheralManagerTest {
    private static final UUID ASSOCIATION_SERVICE_UUID = UUID.randomUUID();
    private static final UUID WRITE_UUID = UUID.randomUUID();
    private static final UUID READ_UUID = UUID.randomUUID();
    private static final int DEVICE_NAME_LENGTH_LIMIT = 8;
    private static final String TEST_REMOTE_DEVICE_ADDRESS = "00:11:22:33:AA:BB";
    private static final UUID TEST_REMOTE_DEVICE_ID = UUID.randomUUID();
    private static final String TEST_VERIFICATION_CODE = "000000";
    private static final byte[] TEST_KEY = "Key".getBytes();
    private static String sAdapterName;

    @Mock private BlePeripheralManager mMockPeripheralManager;
    @Mock private ConnectedDeviceStorage mMockStorage;

    private CarBlePeripheralManager mCarBlePeripheralManager;

    private MockitoSession mMockitoSession;

    @BeforeClass
    public static void beforeSetUp() {
        sAdapterName = BluetoothAdapter.getDefaultAdapter().getName();
    }
    @Before
    public void setUp() {
        mMockitoSession = mockitoSession()
                .initMocks(this)
                .strictness(Strictness.LENIENT)
                .startMocking();
        mCarBlePeripheralManager = new CarBlePeripheralManager(mMockPeripheralManager, mMockStorage,
                ASSOCIATION_SERVICE_UUID, WRITE_UUID, READ_UUID);
    }

    @After
    public void tearDown() {
        if (mCarBlePeripheralManager != null) {
            mCarBlePeripheralManager.stop();
        }
        if (mMockitoSession != null) {
            mMockitoSession.finishMocking();
        }
    }

    @AfterClass
    public static void afterTearDown() {
        BluetoothAdapter.getDefaultAdapter().setName(sAdapterName);
    }

    @Test
    public void testStartAssociationAdvertisingSuccess() {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        String testDeviceName = getNameForAssociation();
        startAssociation(callback, testDeviceName);
        ArgumentCaptor<AdvertiseData> dataCaptor = ArgumentCaptor.forClass(AdvertiseData.class);
        verify(mMockPeripheralManager, timeout(3000)).startAdvertising(any(),
                dataCaptor.capture(), any());
        AdvertiseData data = dataCaptor.getValue();
        assertThat(data.getIncludeDeviceName()).isTrue();
        ParcelUuid expected = new ParcelUuid(ASSOCIATION_SERVICE_UUID);
        assertThat(data.getServiceUuids().get(0)).isEqualTo(expected);
        assertThat(BluetoothAdapter.getDefaultAdapter().getName()).isEqualTo(testDeviceName);
    }

    @Test
    public void testStartAssociationAdvertisingFailure() throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        startAssociation(callback, getNameForAssociation());
        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
                ArgumentCaptor.forClass(AdvertiseCallback.class);
        verify(mMockPeripheralManager, timeout(3000))
                .startAdvertising(any(), any(), callbackCaptor.capture());
        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
        int testErrorCode = 2;
        advertiseCallback.onStartFailure(testErrorCode);
        assertThat(tryAcquire(semaphore)).isTrue();
        verify(callback).onAssociationStartFailure();
    }

    @Test
    public void testNotifyAssociationSuccess() throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        String testDeviceName = getNameForAssociation();
        startAssociation(callback, testDeviceName);
        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
                ArgumentCaptor.forClass(AdvertiseCallback.class);
        verify(mMockPeripheralManager, timeout(3000))
                .startAdvertising(any(), any(), callbackCaptor.capture());
        AdvertiseCallback advertiseCallback = callbackCaptor.getValue();
        AdvertiseSettings settings = new AdvertiseSettings.Builder().build();
        advertiseCallback.onStartSuccess(settings);
        assertThat(tryAcquire(semaphore)).isTrue();
        verify(callback).onAssociationStartSuccess(eq(testDeviceName));
    }

    @Test
    public void testShowVerificationCode() throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        SecureBleChannel channel = getChannelForAssociation(callback);
        channel.getShowVerificationCodeListener().showVerificationCode(TEST_VERIFICATION_CODE);
        assertThat(tryAcquire(semaphore)).isTrue();
        verify(callback).onVerificationCodeAvailable(eq(TEST_VERIFICATION_CODE));
    }

    @Test
    public void testAssociationSuccess() throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        SecureBleChannel channel = getChannelForAssociation(callback);
        SecureBleChannel.Callback channelCallback = channel.getCallback();
        assertThat(channelCallback).isNotNull();
        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
        Key key = EncryptionRunnerFactory.newDummyRunner().keyOf(TEST_KEY);
        channelCallback.onSecureChannelEstablished();
        ArgumentCaptor<AssociatedDevice> deviceCaptor =
                ArgumentCaptor.forClass(AssociatedDevice.class);
        verify(mMockStorage).addAssociatedDeviceForActiveUser(deviceCaptor.capture());
        AssociatedDevice device = deviceCaptor.getValue();
        assertThat(device.getDeviceId()).isEqualTo(TEST_REMOTE_DEVICE_ID.toString());
        assertThat(tryAcquire(semaphore)).isTrue();
        verify(callback).onAssociationCompleted(eq(TEST_REMOTE_DEVICE_ID.toString()));
    }

    @Test
    public void testAssociationFailure_channelError() throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        AssociationCallback callback = createAssociationCallback(semaphore);
        SecureBleChannel channel = getChannelForAssociation(callback);
        SecureBleChannel.Callback channelCallback = channel.getCallback();
        int testErrorCode = 1;
        assertThat(channelCallback).isNotNull();
        channelCallback.onDeviceIdReceived(TEST_REMOTE_DEVICE_ID.toString());
        channelCallback.onEstablishSecureChannelFailure(testErrorCode);
        assertThat(tryAcquire(semaphore)).isTrue();
        verify(callback).onAssociationError(eq(testErrorCode));
    }

    @Test
    public void connectToDevice_stopsAdvertisingAfterTimeout() {
        int timeoutSeconds = 2;
        mCarBlePeripheralManager.connectToDevice(UUID.randomUUID(), timeoutSeconds);
        ArgumentCaptor<AdvertiseCallback> callbackCaptor =
                ArgumentCaptor.forClass(AdvertiseCallback.class);
        verify(mMockPeripheralManager).startAdvertising(any(), any(), callbackCaptor.capture());
        callbackCaptor.getValue().onStartSuccess(null);
        verify(mMockPeripheralManager, timeout(TimeUnit.SECONDS.toMillis(timeoutSeconds + 1)))
                .stopAdvertising(any(AdvertiseCallback.class));
    }

    private BlePeripheralManager.Callback startAssociation(AssociationCallback callback,
            String deviceName) {
        ArgumentCaptor<BlePeripheralManager.Callback> callbackCaptor =
                ArgumentCaptor.forClass(BlePeripheralManager.Callback.class);
        mCarBlePeripheralManager.startAssociation(deviceName, callback);
        verify(mMockPeripheralManager, timeout(3000)).registerCallback(callbackCaptor.capture());
        return callbackCaptor.getValue();
    }

    private SecureBleChannel getChannelForAssociation(AssociationCallback callback) {
        BlePeripheralManager.Callback bleManagerCallback = startAssociation(callback,
                getNameForAssociation());
        BluetoothDevice bluetoothDevice = BluetoothAdapter.getDefaultAdapter()
                .getRemoteDevice(TEST_REMOTE_DEVICE_ADDRESS);
        bleManagerCallback.onRemoteDeviceConnected(bluetoothDevice);
        return mCarBlePeripheralManager.getConnectedDeviceChannel();
    }

    private boolean tryAcquire(Semaphore semaphore) throws InterruptedException {
        return semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
    }

    private String getNameForAssociation() {
        return ByteUtils.generateRandomNumberString(DEVICE_NAME_LENGTH_LIMIT);

    }

    @NonNull
    private AssociationCallback createAssociationCallback(@NonNull final Semaphore semaphore) {
        return spy(new AssociationCallback() {
            @Override
            public void onAssociationStartSuccess(String deviceName) {
                semaphore.release();
            }
            @Override
            public void onAssociationStartFailure() {
                semaphore.release();
            }

            @Override
            public void onAssociationError(int error) {
                semaphore.release();
            }

            @Override
            public void onVerificationCodeAvailable(String code) {
                semaphore.release();
            }

            @Override
            public void onAssociationCompleted(String deviceId) {
                semaphore.release();
            }
        });
    }
}
