package com.google.android.mobly.snippet.bundled.bluetooth.profiles;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import androidx.test.platform.app.InstrumentationRegistry;
import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.bundled.bluetooth.BluetoothAdapterSnippet;
import com.google.android.mobly.snippet.bundled.bluetooth.PairingBroadcastReceiver;
import com.google.android.mobly.snippet.bundled.utils.JsonSerializer;
import com.google.android.mobly.snippet.bundled.utils.Utils;
import com.google.android.mobly.snippet.rpc.Rpc;
import com.google.android.mobly.snippet.rpc.RpcMinSdk;
import java.util.ArrayList;

public class BluetoothHearingAidSnippet implements Snippet {
    private static class BluetoothHearingAidSnippetException extends Exception {
        private static final long serialVersionUID = 1;

        BluetoothHearingAidSnippetException(String msg) {
            super(msg);
        }
    }

    private static final int TIMEOUT_SEC = 60;
    
    private Context context;
    private static boolean isHearingAidProfileReady = false;
    private static BluetoothHearingAid hearingAidProfile;
    private final JsonSerializer jsonSerializer = new JsonSerializer();

    @TargetApi(Build.VERSION_CODES.Q)
    public BluetoothHearingAidSnippet() {
        context = InstrumentationRegistry.getInstrumentation().getContext();
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bluetoothAdapter.getProfileProxy(
                context, new HearingAidServiceListener(), BluetoothProfile.HEARING_AID);
        Utils.waitUntil(() -> isHearingAidProfileReady, TIMEOUT_SEC);
    }

    @TargetApi(Build.VERSION_CODES.Q)
    private static class HearingAidServiceListener implements BluetoothProfile.ServiceListener {
        public void onServiceConnected(int var1, BluetoothProfile profile) {
            hearingAidProfile = (BluetoothHearingAid) profile;
            isHearingAidProfileReady = true;
        }

        public void onServiceDisconnected(int var1) {
            isHearingAidProfileReady = false;
        }
    }

    @TargetApi(Build.VERSION_CODES.Q)
    @RpcMinSdk(Build.VERSION_CODES.Q)
    @Rpc(description = "Connects to a paired or discovered device with HA profile.")
    public void btHearingAidConnect(String deviceAddress) throws Throwable {
        BluetoothDevice device = BluetoothAdapterSnippet.getKnownDeviceByAddress(deviceAddress);
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
        context.registerReceiver(new PairingBroadcastReceiver(context), filter);
        Utils.invokeByReflection(hearingAidProfile, "connect", device);
        if (!Utils.waitUntil(
                () ->
                        hearingAidProfile.getConnectionState(device)
                                == BluetoothHearingAid.STATE_CONNECTED,
                TIMEOUT_SEC)) {
            throw new BluetoothHearingAidSnippetException(
                    String.format(
                            "Failed to connect to device %s|%s with HA profile within %d sec.",
                            device.getName(), device.getAddress(), TIMEOUT_SEC));
        }
    }

    @Rpc(description = "Disconnects a device from HA profile.")
    public void btHearingAidDisconnect(String deviceAddress) throws Throwable {
        BluetoothDevice device = getConnectedBluetoothDevice(deviceAddress);
        Utils.invokeByReflection(hearingAidProfile, "disconnect", device);
        if (!Utils.waitUntil(
                () ->
                        hearingAidProfile.getConnectionState(device)
                                == BluetoothHearingAid.STATE_DISCONNECTED,
                TIMEOUT_SEC)) {
            throw new BluetoothHearingAidSnippetException(
                    String.format(
                            "Failed to disconnect to device %s|%s with HA profile within %d sec.",
                            device.getName(), device.getAddress(), TIMEOUT_SEC));
        }
    }

    @Rpc(description = "Gets all the devices currently connected via HA profile.")
    public ArrayList<Bundle> btHearingAidGetConnectedDevices() {
        return jsonSerializer.serializeBluetoothDeviceList(hearingAidProfile.getConnectedDevices());
    }

    private BluetoothDevice getConnectedBluetoothDevice(String deviceAddress)
            throws BluetoothHearingAidSnippetException {
        for (BluetoothDevice device : hearingAidProfile.getConnectedDevices()) {
            if (device.getAddress().equalsIgnoreCase(deviceAddress)) {
                return device;
            }
        }
        throw new BluetoothHearingAidSnippetException(String.format(
                "No device with address %s is connected via HA Profile.", deviceAddress));
    }

    @Override
    public void shutdown() {}
}

@@ -904,16 +904,53 @@
 MinSdk;%0A
+import com.google.common.base.Ascii;%0A
 import j
@@ -1315,20 +1315,16 @@
 C = 60;%0A
-    
 %0A    pri
@@ -1328,16 +1328,22 @@
 private 
+final 
 Context 
@@ -2125,16 +2125,34 @@
 tener %7B%0A
+        @Override%0A
         
@@ -2335,24 +2335,42 @@
 %0A        %7D%0A%0A
+        @Override%0A
         publ
@@ -4648,16 +4648,23 @@
 private 
+static 
 Bluetoot
@@ -4879,45 +4879,52 @@
 if (
-device.getAddress().equalsIgnoreCase(
+Ascii.equalsIgnoreCase(device.getAddress(), 
 devi

Fix "JavaCodeClarity" problem for BluetoothHearingAidSnippet (#122)