package com.polidea.rxandroidble2.internal.util;

import android.annotation.TargetApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.polidea.rxandroidble2.internal.RxBleLog;
import java.util.List;
import java.util.Set;

import bleshadow.javax.inject.Inject;

public class RxBleAdapterWrapper {

    private final BluetoothAdapter bluetoothAdapter;

    @Inject
    public RxBleAdapterWrapper(@Nullable BluetoothAdapter bluetoothAdapter) {
        this.bluetoothAdapter = bluetoothAdapter;
    }

    public BluetoothDevice getRemoteDevice(String macAddress) {
        if (bluetoothAdapter == null) {
            return null;
        }
        return bluetoothAdapter.getRemoteDevice(macAddress);
    }

    public boolean hasBluetoothAdapter() {
        return bluetoothAdapter != null;
    }

    public boolean isBluetoothEnabled() {
        return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
    }

    @SuppressWarnings("deprecation")
    public boolean startLegacyLeScan(BluetoothAdapter.LeScanCallback leScanCallback) {
        if (bluetoothAdapter == null) {
            return false;
        }
        return bluetoothAdapter.startLeScan(leScanCallback);
    }

    @SuppressWarnings("deprecation")
    public void stopLegacyLeScan(BluetoothAdapter.LeScanCallback leScanCallback) {
        if (bluetoothAdapter == null) {
            return;
        }
        bluetoothAdapter.stopLeScan(leScanCallback);
    }

    @TargetApi(21 /* Build.VERSION_CODES.LOLLIPOP */)
    public void startLeScan(List<ScanFilter> scanFilters, ScanSettings scanSettings, ScanCallback scanCallback) {
        if (bluetoothAdapter == null) {
            return;
        }
        bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilters, scanSettings, scanCallback);
    }

    @RequiresApi(26 /* Build.VERSION_CODES.O */)
    public int startLeScan(List<ScanFilter> scanFilters, ScanSettings scanSettings, PendingIntent callbackIntent) {
        if (bluetoothAdapter == null) {
            return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
        }
        return bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilters, scanSettings, callbackIntent);
    }

    @RequiresApi(26 /* Build.VERSION_CODES.O */)
    public void stopLeScan(PendingIntent callbackIntent) {
        if (bluetoothAdapter == null) {
            return;
        }
        bluetoothAdapter.getBluetoothLeScanner().stopScan(callbackIntent);
    }

    @TargetApi(21 /* Build.VERSION_CODES.LOLLIPOP */)
    public void stopLeScan(ScanCallback scanCallback) {
        if (bluetoothAdapter == null) {
            return;
        }
        if (!bluetoothAdapter.isEnabled()) {
            // this situation seems to be a problem since API 29
            RxBleLog.v(
                    "BluetoothAdapter is disabled, calling BluetoothLeScanner.stopScan(ScanCallback) may cause IllegalStateException"
            );
            // if stopping the scan is not possible due to BluetoothAdapter turned off then it is probably stopped anyway
            return;
        }
        final BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
        if (bluetoothLeScanner == null) {
            RxBleLog.w(
                    "Cannot call BluetoothLeScanner.stopScan(ScanCallback) on 'null' reference; BluetoothAdapter.isEnabled() == %b",
                    bluetoothAdapter.isEnabled()
            );
            // if stopping the scan is not possible due to BluetoothLeScanner not accessible then it is probably stopped anyway
            // this should not happen since the check for BluetoothAdapter.isEnabled() has been added above. This situation was only
            // observed when the adapter was disabled
            return;
        }
        bluetoothLeScanner.stopScan(scanCallback);
    }

    public Set<BluetoothDevice> getBondedDevices() {
        if (bluetoothAdapter == null) {
            return null;
        }
        return bluetoothAdapter.getBondedDevices();
    }
}

@@ -449,16 +449,74 @@
 esApi;%0A%0A
+import com.polidea.rxandroidble2.exceptions.BleException;%0A
 import c
@@ -559,16 +559,16 @@
 BleLog;%0A
-
 import j
@@ -732,16 +732,124 @@
 Adapter;
+%0A    %0A    private static BleException NULL_BLUETOOTH_ADAPTER = new BleException(%22bluetoothAdapter is null%22);
 %0A%0A    @I
@@ -1101,35 +1101,52 @@
             
-return null
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A        %7D%0A
@@ -1606,20 +1606,36 @@
     
-return false
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A  
@@ -1874,38 +1874,60 @@
 ) %7B%0A            
-return
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A        %7D%0A    
@@ -2194,38 +2194,60 @@
 ) %7B%0A            
-return
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A        %7D%0A    
@@ -2571,53 +2571,35 @@
     
-return ScanCallback.SCAN_FAILED_INTERNAL_ERRO
+throw NULL_BLUETOOTH_ADAPTE
 R;%0A 
@@ -2876,38 +2876,60 @@
 ) %7B%0A            
-return
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A        %7D%0A    
@@ -3160,38 +3160,60 @@
 ) %7B%0A            
-return
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A        %7D%0A    
@@ -4514,19 +4514,36 @@
     
-return null
+throw NULL_BLUETOOTH_ADAPTER
 ;%0A  

Throw exception when methods called when bluetoothAdapter is null