/*
 * Copyright 2022 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 android.bluetooth.cts;

import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;

import static org.junit.Assert.assertThrows;

import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Build;
import android.os.ParcelUuid;
import android.test.AndroidTestCase;
import android.util.Log;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.ApiLevelUtil;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class BluetoothCsipSetCoordinatorTest extends AndroidTestCase {
    private static final String TAG = BluetoothCsipSetCoordinatorTest.class.getSimpleName();

    private static final int PROXY_CONNECTION_TIMEOUT_MS = 500;  // ms timeout for Proxy Connect

    private boolean mHasBluetooth;
    private BluetoothAdapter mAdapter;

    private BluetoothCsipSetCoordinator mBluetoothCsipSetCoordinator;
    private boolean mIsCsipSetCoordinatorSupported;
    private boolean mIsProfileReady;
    private Condition mConditionProfileIsConnected;
    private ReentrantLock mProfileConnectedlock;
    private boolean mGroupLockCallbackCalled;
    private TestCallback mTestCallback;
    private Executor mTestExecutor;
    private BluetoothDevice mTestDevice;
    private boolean mIsLocked;
    private int mTestOperationStatus;
    private int mTestGroupId;

    class TestCallback implements BluetoothCsipSetCoordinator.ClientLockCallback {
        @Override
        public void onGroupLockSet(int groupId, int opStatus, boolean isLocked) {
            mGroupLockCallbackCalled = true;
            assertTrue(groupId == mTestGroupId);
            assertTrue(opStatus == mTestOperationStatus);
            assertTrue(isLocked == mIsLocked);
        }
    };

    @Override
    public void setUp() throws Exception {
        super.setUp();
        if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
            mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
                    PackageManager.FEATURE_BLUETOOTH);

            if (!mHasBluetooth) return;

            TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);

            BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
            mAdapter = manager.getAdapter();
            assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));

            mProfileConnectedlock = new ReentrantLock();
            mConditionProfileIsConnected  = mProfileConnectedlock.newCondition();
            mIsProfileReady = false;
            mBluetoothCsipSetCoordinator = null;

            boolean isLeAudioSupportedInConfig =
                     TestUtils.isProfileEnabled(BluetoothProfile.LE_AUDIO);
            boolean isCsipConfigEnabled =
                     TestUtils.isProfileEnabled(BluetoothProfile.CSIP_SET_COORDINATOR);
            if (isLeAudioSupportedInConfig) {
                assertEquals(BluetoothStatusCodes.FEATURE_SUPPORTED, mAdapter.isLeAudioSupported());
                /* If Le Audio is supported then CSIP shall be supported */
                assertTrue("Config must be true when profile is supported", isCsipConfigEnabled);
            }

            if (isCsipConfigEnabled) {
                mIsCsipSetCoordinatorSupported = mAdapter.getProfileProxy(getContext(),
                        new BluetoothCsipServiceListener(),
                        BluetoothProfile.CSIP_SET_COORDINATOR);
                assertTrue("Service shall be supported ", mIsCsipSetCoordinatorSupported);

                mTestCallback = new TestCallback();
                mTestExecutor = mContext.getMainExecutor();
            }
        }
    }

    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        if (mHasBluetooth) {
            if (mBluetoothCsipSetCoordinator != null) {
                mBluetoothCsipSetCoordinator.close();
                mBluetoothCsipSetCoordinator = null;
                mIsProfileReady = false;
                mTestDevice = null;
                mIsLocked = false;
                mTestOperationStatus = 0;
                mTestCallback = null;
                mTestExecutor = null;
            }
            mAdapter = null;
            TestUtils.dropPermissionAsShellUid();
        }
    }

    public void testGetConnectedDevices() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));

        // Verify returns empty list if bluetooth is not enabled
        List<BluetoothDevice> connectedDevices = mBluetoothCsipSetCoordinator.getConnectedDevices();
        assertTrue(connectedDevices.isEmpty());
    }

    public void testGetDevicesMatchingConnectionStates() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));

        // Verify returns empty list if bluetooth is not enabled
        List<BluetoothDevice> connectedDevices =
                mBluetoothCsipSetCoordinator.getDevicesMatchingConnectionStates(null);
        assertTrue(connectedDevices.isEmpty());
    }

    public void testGetGroupUuidMapByDevice() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        mTestDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");

        TestUtils.dropPermissionAsShellUid();
        // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
        assertThrows(SecurityException.class, () ->
                mBluetoothCsipSetCoordinator.getGroupUuidMapByDevice(mTestDevice));

        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);

        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));

        Map<Integer, ParcelUuid> result = mBluetoothCsipSetCoordinator
                .getGroupUuidMapByDevice(mTestDevice);
        assertTrue(result.isEmpty());
    }

    public void testLockUnlockGroup() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        mTestGroupId = 1;
         // Verify parameter
        assertThrows(NullPointerException.class, () ->
                mBluetoothCsipSetCoordinator.lockGroup(mTestGroupId, null, mTestCallback));
        assertThrows(NullPointerException.class, () ->
                mBluetoothCsipSetCoordinator.lockGroup(mTestGroupId, mTestExecutor, null));

        TestUtils.dropPermissionAsShellUid();
        // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
        assertThrows(SecurityException.class,
                () -> mBluetoothCsipSetCoordinator.lockGroup(mTestGroupId, mTestExecutor,
                                                            mTestCallback));

        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);

        // Lock group
        mIsLocked = false;
        mTestOperationStatus = BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID;
        try {
            mBluetoothCsipSetCoordinator.lockGroup(mTestGroupId,
                    mTestExecutor, mTestCallback);
        } catch (Exception e) {
            fail("Exception caught from register(): " + e.toString());
        }

        long uuidLsb = 0x01;
        long uuidMsb = 0x01;
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        try {
            mBluetoothCsipSetCoordinator.unlockGroup(uuid);
        } catch (Exception e) {
            fail("Exception caught from register(): " + e.toString());
        }
    }

    public void testTestLockCallback() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        /* Note. This is just for api coverage until proper testing tools are set up */
        mTestGroupId = 1;
        mTestOperationStatus = 1;
        mIsLocked = true;

        mTestCallback.onGroupLockSet(mTestGroupId, mTestOperationStatus, mIsLocked);
        assertTrue(mGroupLockCallbackCalled);
    }

    public void testGetAllGroupIds() {
        if (!(mHasBluetooth && mIsCsipSetCoordinatorSupported)) return;

        assertTrue(waitForProfileConnect());
        assertNotNull(mBluetoothCsipSetCoordinator);

        TestUtils.dropPermissionAsShellUid();
        assertThrows(SecurityException.class, () ->
                mBluetoothCsipSetCoordinator.getAllGroupIds(BluetoothUuid.CAP));

        TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);

        assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
        List<Integer> result = mBluetoothCsipSetCoordinator.getAllGroupIds(null);
        assertTrue(result.isEmpty());
    }

    private boolean waitForProfileConnect() {
        mProfileConnectedlock.lock();
        try {
            // Wait for the Adapter to be disabled
            while (!mIsProfileReady) {
                if (!mConditionProfileIsConnected.await(
                        PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    // Timeout
                    Log.e(TAG, "Timeout while waiting for Profile Connect");
                    break;
                } // else spurious wakeups
            }
        } catch (InterruptedException e) {
            Log.e(TAG, "waitForProfileConnect: interrrupted");
        } finally {
            mProfileConnectedlock.unlock();
        }
        return mIsProfileReady;
    }

    private final class BluetoothCsipServiceListener implements
            BluetoothProfile.ServiceListener {

        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            mProfileConnectedlock.lock();
            mBluetoothCsipSetCoordinator = (BluetoothCsipSetCoordinator) proxy;
            mIsProfileReady = true;
            try {
                mConditionProfileIsConnected.signal();
            } finally {
                mProfileConnectedlock.unlock();
            }
        }

        @Override
        public void onServiceDisconnected(int profile) {
        }
    }
}
