// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.webauth.authenticator;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.os.ParcelUuid;

import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;

import java.io.Closeable;
import java.util.UUID;

class BLEAdvert implements Closeable {
    private static final String TAG = "CableBLEAdvert";
    // This UUID is allocated to Google.
    private static final String CABLE_UUID = "0000fff9-0000-1000-8000-00805f9b34fb";

    private AdvertiseCallback mCallback;

    BLEAdvert(byte[] payload) {
        assert payload.length == 20;

        BluetoothLeAdvertiser advertiser =
                BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
        if (advertiser == null) {
            // It's possible for the Bluetooth adapter to have been disabled
            // between the previous check and now (crbug.com/123454675). Due to
            // the narrowness of this corner case we don't attempt to watch the
            // adapter in case it is reenabled. Instead the advert is lost and
            // the transaction won't work.
            return;
        }

        mCallback = new AdvertiseCallback() {
            @Override
            public void onStartFailure(int errorCode) {
                Log.i(TAG, "advertising failure " + errorCode);
            }

            @Override
            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                Log.i(TAG, "advertising success");
            }
        };

        AdvertiseSettings settings =
                (new AdvertiseSettings.Builder())
                        .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
                        .setConnectable(false)
                        .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
                        .build();
        ParcelUuid fidoUuid = new ParcelUuid(UUID.fromString(CABLE_UUID));
        AdvertiseData data = (new AdvertiseData.Builder())
                                     .addServiceUuid(fidoUuid)
                                     .addServiceData(fidoUuid, payload)
                                     .setIncludeDeviceName(false)
                                     .setIncludeTxPowerLevel(false)
                                     .build();

        advertiser.startAdvertising(settings, data, mCallback);
    }

    @Override
    @CalledByNative
    public void close() {
        if (mCallback == null) {
            return;
        }

        BluetoothLeAdvertiser advertiser =
                BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
        // The Bluetooth adapter may have been disabled during the transaction.
        if (advertiser != null) {
            Log.i(TAG, "stopping advertising");
            advertiser.stopAdvertising(mCallback);
        }
        mCallback = null;
    }
}
