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

import static com.android.car.connecteddevice.BleStreamProtos.BlePacketProto.BlePacket;
import static com.android.car.connecteddevice.StreamProtos.DeviceMessageProto.BleDeviceMessage;
import static com.android.car.connecteddevice.StreamProtos.OperationProto.OperationType;
import static com.android.car.connecteddevice.connection.DeviceMessageStream.MessageReceivedErrorListener;
import static com.android.car.connecteddevice.connection.DeviceMessageStream.MessageReceivedListener;

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

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

import android.annotation.NonNull;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCharacteristic;

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

import com.android.car.connecteddevice.connection.DeviceMessage;
import com.android.car.connecteddevice.util.ByteUtils;
import com.android.car.protobuf.ByteString;

import org.junit.After;
import org.junit.Before;
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.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public class BleDeviceMessageStreamTest {

    private static final int PACKET_SIZE = 500;

    private BleDeviceMessageStream mStream;

    @Mock
    private BlePeripheralManager mMockBlePeripheralManager;

    @Mock
    private BluetoothDevice mMockBluetoothDevice;

    @Mock
    private BluetoothGattCharacteristic mMockWriteCharacteristic;

    @Mock
    private BluetoothGattCharacteristic mMockReadCharacteristic;

    private MockitoSession mMockingSession;

    @Before
    public void setup() {
        mMockingSession = mockitoSession()
                .initMocks(this)
                .strictness(Strictness.LENIENT)
                .startMocking();

        mStream = new BleDeviceMessageStream(mMockBlePeripheralManager, mMockBluetoothDevice,
                mMockWriteCharacteristic, mMockReadCharacteristic, PACKET_SIZE);
    }

    @After
    public void cleanup() {
        if (mMockingSession != null) {
            mMockingSession.finishMocking();
        }
    }

    @Test
    public void processPacket_notifiesWithEntireMessageForSinglePacketMessage()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
        mStream.setMessageReceivedListener(listener);
        byte[] data = ByteUtils.randomBytes(5);
        processMessage(data);
        assertThat(tryAcquire(semaphore)).isTrue();
        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
        verify(listener).onMessageReceived(messageCaptor.capture(), any());
    }

    @Test
    public void processPacket_notifiesWithEntireMessageForMultiPacketMessage()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
        mStream.setMessageReceivedListener(listener);
        byte[] data = ByteUtils.randomBytes(750);
        processMessage(data);
        assertThat(tryAcquire(semaphore)).isTrue();
        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
        verify(listener).onMessageReceived(messageCaptor.capture(), any());
        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
    }

    @Test
    public void processPacket_receivingMultipleMessagesInParallelParsesSuccessfully()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
        mStream.setMessageReceivedListener(listener);
        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
        List<BlePacket> packets1 = createPackets(data);
        List<BlePacket> packets2 = createPackets(data);

        for (int i = 0; i < packets1.size(); i++) {
            mStream.processPacket(packets1.get(i));
            if (i == packets1.size() - 1) {
                break;
            }
            mStream.processPacket(packets2.get(i));
        }
        assertThat(tryAcquire(semaphore)).isTrue();
        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
        verify(listener).onMessageReceived(messageCaptor.capture(), any());
        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();

        semaphore = new Semaphore(0);
        listener = createMessageReceivedListener(semaphore);
        mStream.setMessageReceivedListener(listener);
        mStream.processPacket(packets2.get(packets2.size() - 1));
        verify(listener).onMessageReceived(messageCaptor.capture(), any());
        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
    }

    @Test
    public void processPacket_doesNotNotifyOfNewMessageIfNotAllPacketsReceived()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        mStream.setMessageReceivedListener(createMessageReceivedListener(semaphore));
        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5));
        List<BlePacket> packets = createPackets(data);
        for (int i = 0; i < packets.size() - 1; i++) {
            mStream.processPacket(packets.get(i));
        }
        assertThat(tryAcquire(semaphore)).isFalse();
    }

    @Test
    public void processPacket_ignoresDuplicatePacket() {
        Semaphore semaphore = new Semaphore(0);
        byte[] data = ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5));
        MessageReceivedListener listener = createMessageReceivedListener(semaphore);
        mStream.setMessageReceivedListener(listener);
        ArgumentCaptor<DeviceMessage> messageCaptor = ArgumentCaptor.forClass(DeviceMessage.class);
        List<BlePacket> packets = createPackets(data);
        for (int i = 0; i < packets.size(); i++) {
            mStream.processPacket(packets.get(i));
            mStream.processPacket(packets.get(i)); // Process each packet twice.
        }
        verify(listener).onMessageReceived(messageCaptor.capture(), any());
        assertThat(Arrays.equals(data, messageCaptor.getValue().getMessage())).isTrue();
    }

    @Test
    public void processPacket_packetBeforeExpectedRangeNotifiesMessageError()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 2.5)));
        mStream.processPacket(packets.get(0));
        mStream.processPacket(packets.get(1));
        mStream.processPacket(packets.get(0));
        assertThat(tryAcquire(semaphore)).isTrue();
    }

    @Test
    public void processPacket_packetAfterExpectedNotifiesMessageError()
            throws InterruptedException {
        Semaphore semaphore = new Semaphore(0);
        mStream.setMessageReceivedErrorListener(createMessageReceivedErrorListener(semaphore));
        List<BlePacket> packets = createPackets(ByteUtils.randomBytes((int) (PACKET_SIZE * 1.5)));
        mStream.processPacket(packets.get(1));
        assertThat(tryAcquire(semaphore)).isTrue();
    }

    @NonNull
    private List<BlePacket> createPackets(byte[] data) {
        try {
            BleDeviceMessage message = BleDeviceMessage.newBuilder()
                    .setPayload(ByteString.copyFrom(data))
                    .setOperation(OperationType.CLIENT_MESSAGE)
                    .build();
            return BlePacketFactory.makeBlePackets(message.toByteArray(),
                    ThreadLocalRandom.current().nextInt(), PACKET_SIZE);
        } catch (Exception e) {
            assertWithMessage("Uncaught exception while making packets.").fail();
            return new ArrayList<>();
        }
    }

    private void processMessage(byte[] data) {
        List<BlePacket> packets = createPackets(data);
        for (BlePacket packet : packets) {
            mStream.processPacket(packet);
        }
    }

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

    @NonNull
    private MessageReceivedListener createMessageReceivedListener(@NonNull Semaphore semaphore) {
        return spy((deviceMessage, operationType) -> semaphore.release());
    }

    @NonNull
    private MessageReceivedErrorListener createMessageReceivedErrorListener(
            @NonNull Semaphore semaphore) {
        return exception -> semaphore.release();
    }
}
