from typing import TYPE_CHECKING, Optional

if TYPE_CHECKING:
    from rpcclient.clients.darwin.client import DarwinClient


class Bluetooth:
    """bluetooth utils"""

    # bugfix: +[BluetoothManager.setSharedInstanceQueue:] cannot be called twice in the same process,
    # so we use this global to tell if it was already called
    _ENV_QUEUE_SET = "_rpc_server_bluetooth_manager_dispatch_queue_set"

    def __init__(self, client: "DarwinClient"):
        self._client = client
        self._client.load_framework("BluetoothManager")
        bluetooth_manager_class = client.symbols.objc_getClass("BluetoothManager")
        if not client.getenv(self._ENV_QUEUE_SET):
            bluetooth_manager_class.objc_call(
                "setSharedInstanceQueue:", self._client.symbols.dispatch_queue_create(0, 0)
            )
            client.setenv(self._ENV_QUEUE_SET, "1")
        self._bluetooth_manager = bluetooth_manager_class.objc_call("sharedInstance")

    def is_on(self):
        return self._bluetooth_manager.objc_call("enabled") == 1

    def turn_on(self):
        self._set(is_on=1)

    def turn_off(self):
        self._set(is_on=0)

    @property
    def address(self) -> Optional[str]:
        return self._bluetooth_manager.objc_call("localAddress").py()

    @property
    def connected(self) -> bool:
        return bool(self._bluetooth_manager.objc_call("connected"))

    @property
    def discoverable(self) -> bool:
        return bool(self._bluetooth_manager.objc_call("isDiscoverable"))

    @discoverable.setter
    def discoverable(self, value: bool):
        self._bluetooth_manager.objc_call("setDiscoverable:", value)

    def _set(self, is_on):
        self._bluetooth_manager.objc_call("setPowered:", is_on)
        self._bluetooth_manager.objc_call("setEnabled:", is_on)

    def __repr__(self):
        return f"<Bluetooth state:{'ON' if self.is_on() else 'OFF'}>"
