/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
 * 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.
 */

import access from '@ohos.bluetooth.access';
import preferences from '@ohos.data.preferences';
import { AbilityContextManager } from '@ohos/settings.common/src/main/ets/ability/AbilityContextManager';
import { BluetoothUtils } from '@ohos/settings.common/src/main/ets/utils/BluetoothUtils';
import { CheckEmptyUtils } from '@ohos/settings.common/src/main/ets/utils/CheckEmptyUtils';
import {
  NUMBER_CLOSE,
  NUMBER_OPEN,
  WIRELESS_ANTI_THEFT_HOST_ADDRESS_KEY,
  WIRELESS_ANTI_THEFT_KEY,
} from '@ohos/settings.common/src/main/ets/utils/Consts';
import { EncryptUtils } from '@ohos/settings.common/src/main/ets/utils/EncryptUtils';
import { LogMaskUtil, LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { ResourceUtil } from '@ohos/settings.common/src/main/ets/utils/ResourceUtil';
import { SettingsDataUtils } from '@ohos/settings.common/src/main/ets/utils/SettingsDataUtils';
import {
  BluetoothAdapter,
  BluetoothBondChangeListener,
  BluetoothBondedDeviceChangeListener,
  BluetoothDeviceChangeListener,
  BluetoothDeviceNameUpdateListener,
  BluetoothProfileStateChangeListener,
  BluetoothStateChangeListener
} from '../BluetoothAdapter';
import {
  BluetoothDevice,
  BondState,
  BondStateParam,
  PinRequiredParam,
  ProfileConnectionState,
  ProfileId,
  StateChangeParam,
} from '../model/BluetoothModel';
import { MenuEntry, MenuEntryData } from '../model/MenuEntry';

/* instrument ignore file */
export const BONDED_DEVICE_TIME_FLAG: number = -2000000000000;

@Observed
export class BluetoothWindowBondDeviceViewModel implements BluetoothBondChangeListener, BluetoothDeviceChangeListener,
BluetoothProfileStateChangeListener, BluetoothStateChangeListener, BluetoothDeviceNameUpdateListener,
BluetoothBondedDeviceChangeListener {
  public tag: string = 'BluetoothWindowBondDeviceViewModel : ';
  public bondDevicesMenu: MenuEntry[] = [];
  // 无线防盗标志位
  private isWirelessAntiTheft: boolean = false;
  private wirelessAntiTheftHostAddress: string = '';

  getListenKey(): string {
    return 'Bluetooth_Window_Bond_Device_View_Model';
  }

  init(bondDevicesMenu: MenuEntry[]): void {
    LogUtil.info(`${this.tag} init`);
    this.bondDevicesMenu = bondDevicesMenu;
    this.registerDataChange();
    // 无线防盗相关 (必须写在 updateBondedDevices 前面)
    this.isWirelessAntiTheft = this.getWirelessAntiTheftState();
    if (this.isWirelessAntiTheft) {
      this.wirelessAntiTheftHostAddress = this.getWirelessAntiTheftHostAddress();
    }
    if (BluetoothUtils.isBluetoothStateOn(BluetoothAdapter.getInstance().currentState)) {
      this.updateBondedDevices();
    }
  }

  destroy(): void {
    LogUtil.info(`${this.tag} destroy`);
    this.bondDevicesMenu.splice(0, this.bondDevicesMenu.length);
    this.unRegisterDataChange();
  }

  /**
   * 获取当前系统设置中的无线防盗,默认false
   */
  private getWirelessAntiTheftState(): boolean {
    // 获取当前系统设置中的允许休眠时通知开关的状态,默认false
    const wirelessAntiTheftState: string = SettingsDataUtils.getSettingsData(WIRELESS_ANTI_THEFT_KEY, NUMBER_CLOSE);
    LogUtil.info(`${this.tag} getWirelessAntiTheftState. wirelessAntiTheftState:${wirelessAntiTheftState}`);
    return wirelessAntiTheftState === NUMBER_OPEN;
  }

  /**
   * 获取当前系统设置中的无线防盗蓝牙地址,默认空字符串
   */
  private getWirelessAntiTheftHostAddress(): string {
    // 获取当前系统设置中的允许休眠时通知开关的状态,默认false
    const hostAddress: string = SettingsDataUtils.getSettingsData(WIRELESS_ANTI_THEFT_HOST_ADDRESS_KEY, '');
    LogUtil.info(`${this.tag} getWirelessAntiTheftHostAddress. hostAddress:${BluetoothUtils.getLogMAC(hostAddress)}`);
    return hostAddress;
  }

  updateBondedDevices(): void {
    LogUtil.info(`${this.tag} updateBondedDevices`);
    let devices = BluetoothAdapter.getInstance().getBondedDevices();
    if (!devices) {
      LogUtil.info(`${this.tag} bonded devices is empty`);
      return;
    }

    for (let device of devices) {
      this.addBondDevice((BluetoothAdapter.getInstance().cachedBondedDevices.get(device.deviceId) ||
        new BluetoothDevice(device.deviceId)), 0);
      if (this.bondDevicesMenu.length > 0) {
        this.getFromPreferenceAndSort(device, this.bondDevicesMenu[this.bondDevicesMenu.length - 1]);
      }
    }
  }

  private addBondDevice(device: BluetoothDevice, bondTime: number): void {
    LogUtil.info(`${this.tag} add bond device, deviceId: ${BluetoothUtils.getLogMAC(device?.deviceId)}`);
    if (!device) {
      LogUtil.error(`${this.tag} add bond device fail, device is invalid`);
      return;
    }
    if (this.findMenuEntry(device.deviceId) !== -1) {
      LogUtil.warn(`${this.tag} add bond device fail, has contain the device`);
      return;
    }
    if (this.isWirelessAntiTheft && device.deviceId === this.wirelessAntiTheftHostAddress) {
      LogUtil.warn(`${this.tag} add bond device fail, it is wirelessAntiTheft device`);
      return;
    }
    this.bondDevicesMenu.push(this.createMenuEntry(device, bondTime));
  }

  private createMenuEntry(device: BluetoothDevice, bondTime: number, isShow: boolean = false): MenuEntry {
    let param: MenuEntryData = {
      key: device.deviceId,
      title: device.deviceName,
      rssi: 0,
      icon: device.getIcon(),
    };
    let a2dpState: ProfileConnectionState =
      BluetoothAdapter.getInstance().getProfileState(ProfileId.PROFILE_A2DP_SOURCE, device.deviceId);
    let hfpState: ProfileConnectionState =
      BluetoothAdapter.getInstance().getProfileState(ProfileId.PROFILE_HANDS_FREE_AUDIO_GATEWAY, device.deviceId);
    let hidState: ProfileConnectionState =
      BluetoothAdapter.getInstance().getProfileState(ProfileId.PROFILE_HID_HOST, device.deviceId);
    let hearingAidState: ProfileConnectionState =
      BluetoothAdapter.getInstance().getProfileState(ProfileId.PROFILE_HEARING_AID, device.deviceId);
    if (device.getSubDevice()) {
      let subDeviceState: ProfileConnectionState = BluetoothAdapter.getInstance()
        .getProfileState(ProfileId.PROFILE_HEARING_AID, (device.getSubDevice() as BluetoothDevice).deviceId);
      LogUtil.info(`${this.tag} createMenuEntry mainDeviceState :${hearingAidState}, subDeviceState : ${subDeviceState}`);
      hearingAidState = BluetoothDevice.mergeHearingAidState(hearingAidState, subDeviceState);
    }
    param.isConnect = [a2dpState, hfpState, hidState, hearingAidState].includes(ProfileConnectionState.STATE_CONNECTED);
    param.index = param.isConnect ? (BONDED_DEVICE_TIME_FLAG + bondTime) :
      ((bondTime === 0) ? this.bondDevicesMenu.length : bondTime);
    param.subTitle = this.getSubtitle(device.deviceId, a2dpState, hfpState, hidState, hearingAidState);
    LogUtil.info(`${this.tag} getSubtitle : ${param.subTitle}`);
    return new MenuEntry(param);
  }

  private getSubtitle(deviceId: string, a2dpState: ProfileConnectionState, hfpState: ProfileConnectionState,
    hidState: ProfileConnectionState, hearingAidState: ProfileConnectionState): ResourceStr {
    LogUtil.info(`${this.tag} getSubtitle a2dpState : ${a2dpState}, hfpState : ${hfpState}, hidState : ${hidState}, hearingAidState : ${hearingAidState}`);
    let lastSubtitle: ResourceStr = '';
    let index: number = this.findMenuEntry(deviceId);
    if (index !== -1 && index < this.bondDevicesMenu.length) {
      lastSubtitle = this.bondDevicesMenu[index].subTitle;
    }

    let subtitle: string = '';
    if ([a2dpState, hfpState, hidState, hearingAidState].includes(ProfileConnectionState.STATE_CONNECTING)) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_connecting_summary'));
      return subtitle;
    }
    if (a2dpState === ProfileConnectionState.STATE_CONNECTED && hfpState === ProfileConnectionState.STATE_CONNECTED) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_hfp_a2dp_connect_summary'));
      return subtitle;
    }
    if (a2dpState === ProfileConnectionState.STATE_CONNECTED &&
      hfpState === ProfileConnectionState.STATE_DISCONNECTED) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_a2dp_connect_summary'));
      return subtitle;
    }
    if (a2dpState === ProfileConnectionState.STATE_DISCONNECTED &&
      hfpState === ProfileConnectionState.STATE_CONNECTED) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_hfp_connect_summary'));
      return subtitle;
    }
    if (hidState === ProfileConnectionState.STATE_CONNECTED ||
      hearingAidState === ProfileConnectionState.STATE_CONNECTED) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_connected_summary'));
      return subtitle;
    }
    if ([a2dpState, hfpState, hidState].includes(ProfileConnectionState.STATE_DISCONNECTING)) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_disconnecting_summary'));
      return subtitle;
    }
    if (lastSubtitle === ResourceUtil.getWindowsStringSync($r('app.string.bt_connecting_summary'))) {
      subtitle = ResourceUtil.getWindowsStringSync($r('app.string.bt_connect_failed_title'));
      return subtitle;
    }

    return subtitle;
  }

  private findMenuEntry(deviceId: string): number {
    for (let index = 0; index < this.bondDevicesMenu.length; index++) {
      if (this.bondDevicesMenu[index].key === deviceId) {
        return index;
      }
    }
    return -1;
  }

  private compareMenu(menu1: MenuEntry, menu2: MenuEntry) {
    if (!menu1) {
      return -1;
    }
    if (!menu2) {
      return 1;
    }
    let a = menu1.index as number;
    let b = menu2.index as number;
    return a - b;
  }

  private registerDataChange(): void {
    BluetoothAdapter.getInstance().unRegisterStateChangeListener(this);
    BluetoothAdapter.getInstance().registerStateChangeListener(this);

    BluetoothAdapter.getInstance().unRegisterBondChangeListener(this);
    BluetoothAdapter.getInstance().registerBondChangeListener(this);

    BluetoothAdapter.getInstance().unRegisterProfileStateChangeListener(this);
    BluetoothAdapter.getInstance().registerProfileStateChangeListener(this);

    BluetoothAdapter.getInstance().unRegisterDeviceNameUpdateListener(this);
    BluetoothAdapter.getInstance().registerDeviceNameUpdateListener(this);

    BluetoothAdapter.getInstance().unRegisterDeviceChangeListener(this);
    BluetoothAdapter.getInstance().registerDeviceChangeListener(this);

    BluetoothAdapter.getInstance().unregisterBondedDeviceChangeListener(this);
    BluetoothAdapter.getInstance().registerBondedDeviceChangeListener(this);
  }

  private unRegisterDataChange(): void {
    LogUtil.info(`${this.tag} unRegisterDataChange`);
    BluetoothAdapter.getInstance().unRegisterStateChangeListener(this);
    BluetoothAdapter.getInstance().unRegisterBondChangeListener(this);
    BluetoothAdapter.getInstance().unRegisterProfileStateChangeListener(this);
    BluetoothAdapter.getInstance().unRegisterDeviceNameUpdateListener(this);
    BluetoothAdapter.getInstance().unRegisterDeviceChangeListener(this);
    BluetoothAdapter.getInstance().unregisterBondedDeviceChangeListener(this);
  }

  onBluetoothStateChange(state: number): void {
    LogUtil.info(`${this.tag} bluetooth state change: ${state}`);
    if (BluetoothUtils.isBluetoothStateOn(state)) { // 开启
      this.updateBondedDevices();
    } else {
      this.bondDevicesMenu.splice(0, this.bondDevicesMenu.length);
    }
  }

  onDeviceNameUpdate(device: BluetoothDevice): void {
    LogUtil.info(`${this.tag} onDeviceNameUpdate deviceId: ${BluetoothUtils.getLogMAC(device?.deviceId)}, newDeviceName: ${LogMaskUtil.getLogNickNameString(device?.deviceName)}`);
    if (!device || CheckEmptyUtils.checkStrIsEmpty(device?.deviceName)) {
      LogUtil.error(`${this.tag} device or deviceName is invalid`);
      return;
    }
    let index: number = this.findMenuEntry(device.deviceId)
    if (index === -1) {
      return;
    }

    this.bondDevicesMenu[index].title = device?.deviceName;
  }

  onBluetoothProfileStateChange(profileId: ProfileId, stateChangeParam: StateChangeParam): void {
    if (!stateChangeParam) {
      return;
    }
    let deviceId = stateChangeParam.deviceId;
    // 如果是附属设备,找到它的主设备,将目标deviceId切换为主设备的deviceId
    if (BluetoothAdapter.getInstance().isBondedSubDevice(deviceId)) {
      let mainDevice = BluetoothAdapter.getInstance().findMainDeviceBySubDevice(deviceId);
      if (mainDevice) {
        deviceId = mainDevice.deviceId;
      }
    }
    let index: number = this.findMenuEntry(deviceId);
    if (index !== -1) {
      let device: BluetoothDevice | undefined = BluetoothAdapter.getInstance().cachedBondedDevices.get(deviceId);
      if (!device) {
        LogUtil.error(`${this.tag} onBluetoothProfileStateChange. foundDevice is empty`);
        return;
      }
      LogUtil.info(`${this.tag} onBluetoothProfileStateChange. index:${index} profileId:${profileId} StateChangeParam:${stateChangeParam.state}`);
      device?.buildProfileSwitchState().then((data) => {
        LogUtil.info(`${this.tag} onBluetoothProfileStateChange. buildProfileSwitchState summary:${data}`);
        let index = this.findMenuEntry(deviceId);
        this.bondDevicesMenu[index].subTitle = data;
        this.updatePluginWindowHeight(access.BluetoothState.STATE_ON);
      });
      if (stateChangeParam.state === ProfileConnectionState.STATE_DISCONNECTED ||
        stateChangeParam.state === ProfileConnectionState.STATE_CONNECTED) {
        let isConnect: boolean = device.isConnected();
        LogUtil.info(`${this.tag} onBluetoothProfileStateChange. connect state change, isConnect:${isConnect}`);
        let data: number = new Date().getTime();
        this.bondDevicesMenu[index].isConnect = isConnect;
        this.bondDevicesMenu[index].index = isConnect ? BONDED_DEVICE_TIME_FLAG - data : -data;
        this.bondDevicesMenu.sort(this.compareMenu);
        this.addToPreference(device.deviceId, data);
      }
    }
  }

  public updatePluginWindowHeight(state?: number): void {
  }

  onConnectResult(deviceId: string, result: number, isSuccess: boolean): void {
    LogUtil.info(`${this.tag} onConnectResult. deviceId:${BluetoothUtils.getLogMAC(deviceId)} isSuccess:${isSuccess}`);
    if (!isSuccess) {
      let device = BluetoothAdapter.getInstance().getBondedDeviceOrSubDevice(deviceId);
      if (!device) {
        LogUtil.error(`${this.tag} onConnectResult. foundDevice is empty`);
        return;
      }
      if (device && device.isHearingAidDevice()) {
        this.onHearingAidConnectFail(device);
        return;
      }
      // 这里将视图设为连接失败
      device?.buildProfileSwitchState(true).then((data) => {
        LogUtil.info(`${this.tag} onConnectResult. summary:${data}`);
        let index = this.findMenuEntry(deviceId);
        this.bondDevicesMenu[index].subTitle = data;
        this.updatePluginWindowHeight(access.BluetoothState.STATE_ON);
      });
    }
  }

  onHearingAidConnectFail(device: BluetoothDevice) {
    LogUtil.info(`${this.tag} onHearingAidConnectFail, deviceId: ${BluetoothUtils.getLogMAC(device?.deviceId)}`);
    let anotherDevice: BluetoothDevice | undefined = undefined;
    let isSubDevice = BluetoothAdapter.getInstance().isBondedSubDevice(device?.deviceId);

    if (isSubDevice) {
      anotherDevice = BluetoothAdapter.getInstance().findMainDeviceBySubDevice(device?.deviceId);
    } else {
      if (device.getSubDevice()) {
        anotherDevice = device.getSubDevice();
      }
    }
    // 如果存在另一个设备,且不为Disconnect状态,不弹失败提示框
    if (anotherDevice &&
      BluetoothAdapter.getInstance().getProfileState(ProfileId.PROFILE_HEARING_AID, anotherDevice.deviceId) !==
      ProfileConnectionState.STATE_DISCONNECTED) {
      LogUtil.info(`${this.tag} onHearingAidConnectFail, anotherDevice is not Disconncted,not show fail Dialog`);
      return;
    }
    let mainDeviceId = device.deviceId;
    if (isSubDevice && anotherDevice) {
      mainDeviceId = anotherDevice?.deviceId;
    }

    let index: number = this.findMenuEntry(mainDeviceId);
    if (index === -1) {
      return;
    }
    // 这里将视图设为连接失败
    device?.buildProfileSwitchState(true).then((data) => {
      LogUtil.info(`${this.tag} onConnectResult. summary:${data}`);
      this.bondDevicesMenu[index].subTitle = data;
      this.updatePluginWindowHeight(access.BluetoothState.STATE_ON);
    });
  }

  onBondDeviceDeleted(deviceId: string): void {
    LogUtil.info(`${this.tag} onBondDeviceDeleted, deviceId: ${BluetoothUtils.getLogMAC(deviceId)}`);
    if (!deviceId) {
      LogUtil.error(`${this.tag} onBondDeviceDeleted param empty`);
      return;
    }

    let index: number = this.findMenuEntry(deviceId);
    if (index === -1) {
      return;
    }
    this.bondDevicesMenu.splice(index, 1);
  }

  onBluetoothBondStateChange(stateParam: BondStateParam): void {
    if (!stateParam) {
      LogUtil.error(`${this.tag} onBluetoothBondStateChange param empty`);
      return;
    }

    LogUtil.info(`${this.tag} onBluetoothBondStateChange, deviceId: ${BluetoothUtils.getLogMAC(stateParam.deviceId)}, state: ${stateParam.state}`);
    let deviceId = stateParam.deviceId;
    if (stateParam.state !== BondState.BOND_STATE_BONDED) {
      this.onBondDeviceDeleted(deviceId);
      this.deleteFromPreference(deviceId);
    }

    if (stateParam.state === BondState.BOND_STATE_BONDED) {
      let bondTime: number = new Date().getTime();
      this.addBondDevice(BluetoothAdapter.getInstance().getBondedDevice(deviceId) ||
      BluetoothDevice.createDevice(deviceId), -bondTime);
      this.bondDevicesMenu.sort(this.compareMenu);
      this.addToPreference(deviceId, bondTime);
    }
  }

  onBluetoothPinRequired(pinRequiredParam: PinRequiredParam): void {
  }

  onPairResult(deviceId: string, result: number, isSuccess: boolean): void {
  }

  onDeviceAdded(device: BluetoothDevice): void {
  }

  onDeviceAttributesChanged(device: BluetoothDevice): void {
    let index: number = this.findMenuEntry(device?.deviceId);
    if (index === -1) {
      return;
    }
    this.bondDevicesMenu[index].icon = device.getIcon();
  }

  onDeviceDeleted(device: BluetoothDevice): void {
  }

  onAvailableDevicesRefresh(): void {
  }

  onAvailableDeviceClear(): void {
  }

  onBondedDeviceMerged(device: BluetoothDevice): void {
    LogUtil.info(`${this.tag} onBondedDeviceMerged ${BluetoothUtils.getLogMAC(device?.deviceId)}`);
    this.onBondDeviceDeleted(device?.deviceId);
  }

  private getFromPreferenceAndSort(device: BluetoothDevice, menuEntry: MenuEntry): void {
    let time = 1;
    this.getFromPreference(device?.deviceId, time).then((bondTime) => {
      LogUtil.info(`${this.tag} getFromPreference ${BluetoothUtils.getLogMAC(device?.deviceId)}, bondTime: ${bondTime}, time: ${time}`);
      if (bondTime > 0) {
        time = bondTime;
        menuEntry.index = device.isConnected() ? BONDED_DEVICE_TIME_FLAG - time : -time;
        this.bondDevicesMenu.sort(this.compareMenu);
      }
    });
  }

  private async getFromPreference(deviceId: string, defValue: number): Promise<number> {
    let pref: preferences.Preferences | undefined = await this.getPreference();
    if (!pref) {
      LogUtil.error(`${this.tag} getFromPreference fail: pref is invalid`);
      return defValue;
    }

    let deviceIdHash: string | undefined = await EncryptUtils.getAegSha256(deviceId);
    if (!deviceIdHash) {
      LogUtil.error(`${this.tag} getFromPreference fail: deviceIdHash is invalid`);
      return defValue;
    }

    let bondTime: number = defValue;
    try {
      bondTime = await pref.get(deviceIdHash, defValue) as number;
      LogUtil.error(`${this.tag} getFromPreference success: ${bondTime}`);
    } catch (err) {
      LogUtil.error(`${this.tag} getFromPreference fail: cause: ${err?.code}, ${err?.message}`);
      bondTime = defValue;
    }

    return bondTime;
  }

  private async addToPreference(deviceId: string, data: number): Promise<void> {
    let pref: preferences.Preferences | undefined = await this.getPreference();
    if (!pref) {
      LogUtil.error(`${this.tag} addToPreference fail: pref is invalid`);
      return;
    }

    let deviceIdHash: string | undefined = await EncryptUtils.getAegSha256(deviceId);
    if (!deviceIdHash) {
      LogUtil.error(`${this.tag} addToPreference fail: deviceIdHash is invalid`);
      return;
    }

    try {
      await pref.put(deviceIdHash, data);
      await pref.flush();
      LogUtil.info(`${this.tag} addToPreference success ${BluetoothUtils.getLogMAC(deviceId)}, ${data}`);
    } catch (err) {
      LogUtil.error(`${this.tag} addToPreference fail: cause: ${err?.message}`);
    }
  }

  private async deleteFromPreference(deviceId: string): Promise<void> {
    let pref: preferences.Preferences | undefined = await this.getPreference();
    if (!pref) {
      LogUtil.error(`${this.tag} deleteFromPreference fail: pref is invalid`);
      return;
    }

    let deviceIdHash: string | undefined = await EncryptUtils.getAegSha256(deviceId);
    if (!deviceIdHash) {
      LogUtil.error(`${this.tag} deleteFromPreference fail: deviceIdHash is invalid`);
      return;
    }

    try {
      await pref.delete(deviceIdHash);
      await pref.flush();
      LogUtil.info(`${this.tag} delete success`);
    } catch (err) {
      LogUtil.error(`${this.tag} deleteFromPreference fail: errCode: ${err?.code}, errMsg: ${err?.message}`);
    }
  }

  private async getPreference(): Promise<preferences.Preferences | undefined> {
    let promisePref: Promise<preferences.Preferences> | undefined;
    try {
      promisePref = preferences.getPreferences(AbilityContextManager.getContext(), 'btBondedDevice');
    } catch (err) {
      LogUtil.error(`${this.tag} getPreferences fail: ${err?.code}, ${err?.message}`);
    }
    return promisePref;
  }

  public handleBondedDeviceItemClick(deviceId: string): void {
    if (CheckEmptyUtils.checkStrIsEmpty(deviceId)) {
      LogUtil.error(`${this.tag} handleBondedDeviceItemClick fail, deviceId is invalid`);
      return;
    }

    let index: number = this.findMenuEntry(deviceId);
    if (index === -1) {
      return;
    }

    LogUtil.info(`${this.tag} handleBondedDeviceItemClick, deviceId: ${BluetoothUtils.getLogMAC(deviceId)}`);
    let menuEntry: MenuEntry = this.bondDevicesMenu[index];
    if (menuEntry.isConnect) {
      this.disconnectDevice(deviceId);
    } else {
      let subDeviceId = BluetoothAdapter.getInstance().cachedBondedDevices.get(deviceId)?.getSubDevice()?.deviceId;
      BluetoothAdapter.getInstance().startConnectIfSupport(deviceId, subDeviceId);
    }
  }

  private disconnectDevice(deviceId: string): void {
    LogUtil.info(`${this.tag} start to disconnect device`);
    let device = BluetoothAdapter.getInstance().getBondedDevice(deviceId);
    if (!device || !device.isConnected()) {
      LogUtil.error(`${this.tag} device not exit or already disconnect, return`);
      return;
    }

    let result = BluetoothAdapter.getInstance().disconnectDevice(device.deviceId);
    let subDevice = device.getSubDevice();
    if (subDevice) {
      result = result && BluetoothAdapter.getInstance().disconnectDevice(subDevice.deviceId);
    }
    LogUtil.info(`${this.tag} disconnectDevice result : ${result}`);
  }
}