"""Definitions of Clients connected to Omada devices."""

from .definitions import (
    AuthenticationStatus,
    ConnectType,
    OmadaApiData,
    RadioId,
    WifiMode,
)


class OmadaNetworkClient(OmadaApiData):
    """Base representation of Omada client"""

    @property
    def connection_time(self) -> int | None:
        """Client connection time in seconds."""
        if "uptime" in self._data:
            return self._data["uptime"]
        if "duration" in self._data:
            return self._data["duration"]
        return None

    @property
    def is_blocked(self) -> bool:
        """Indicates if a client is blocked."""
        # Most API calls return 'blocked' but the 'known_clients' call returns 'block'
        return self._data.get("blocked", self._data.get("block", False))

    @property
    def is_guest(self) -> bool:
        """Indicates if client is a 'guest'."""
        return self._data["guest"]

    @property
    def last_seen(self) -> float:
        """Timestamp in second from Unix Epoch when client was last connected."""
        return self._data["lastSeen"] / 1000

    @property
    def mac(self) -> str:
        """The MAC address of the client."""
        return self._data["mac"]

    @property
    def name(self) -> str:
        """The name of the client."""
        return self._data["name"]

    @property
    def is_wireless(self) -> bool | None:
        """Indicates if client is a wireless client"""
        return self._data.get("wireless")


class OmadaConnectedClient(OmadaNetworkClient):
    """Details of a client connected to an Omada device."""

    @property
    def is_active(self) -> bool:
        """Indicates if client is active"""
        return self._data["active"]

    @property
    def activity(self) -> int:
        """Realtime downlink rate (Byte/s)"""
        return self._data["activity"]

    @property
    def auth_status(self) -> AuthenticationStatus:
        """Authentication status"""
        return self._data["authStatus"]

    @property
    def connect_dev_type(self) -> str | None:
        """Connected device type (ap, gateway, switch)"""
        return self._data.get("connectDevType")

    @property
    def connect_type(self) -> ConnectType:
        """Connection type"""
        return ConnectType(self._data["connectType"])

    @property
    def device_type(self) -> str:
        """Device type (Android, iPhone, iPod... mostly Unkown)"""
        return self._data["deviceType"]

    @property
    def down_packet(self) -> int:
        """Number of packets sent to client"""
        return self._data["downPacket"]

    @property
    def host_name(self) -> str | None:
        """The client's hostname."""
        return self._data.get("hostName")

    @property
    def ip(self) -> str | None:
        """The client's IP address."""
        return self._data.get("ip")

    @property
    def traffic_down(self) -> int:
        """Number of bytes sent to client"""
        return self._data["trafficDown"]

    @property
    def traffic_up(self) -> int:
        """Number of bytes sent by client"""
        return self._data["trafficUp"]

    @property
    def up_packet(self) -> int:
        """Number of packets received from client"""
        return self._data["upPacket"]

    @property
    def vlan(self) -> int | None:
        """
        VLAN ID

        This property appears to work with some access points but is not provided
        by others.

        Known to work on: EAP653
        Not provided by: EAP660
        """
        return self._data.get("vid")


class IpSetting(OmadaApiData):
    """IP settings of a client connected to an Omada device."""

    @property
    def used_fixed_addr(self) -> bool:
        """True if a fixed IP address is reserved."""
        return bool(self._data["useFixedAddr"])


class RateLimit(OmadaApiData):
    """Rate limit settings of a client connected to an Omada device."""

    @property
    def enabled(self) -> bool:
        """True if rate limiting is enabled."""
        return bool(self._data["enable"])

    @property
    def down_enabled(self) -> bool:
        """True if downstream rate limiting is enabled."""
        return bool(self._data["downEnable"])

    @property
    def down_limit(self) -> int:
        """Downstream rate limit."""
        return int(self._data["downLimit"])

    @property
    def down_unit(self) -> int:
        """Downstream rate limit unit (Enum)."""
        return int(self._data["downUnit"])

    @property
    def up_enabled(self) -> bool:
        """True if upstream rate limiting is enabled."""
        return bool(self._data["upEnable"])

    @property
    def up_limit(self) -> int:
        """Upstream rate limit."""
        return int(self._data["upLimit"])

    @property
    def up_unit(self) -> int:
        """Upstream rate limit unit (Enum)."""
        return int(self._data["upUnit"])


class OmadaClientDetails(OmadaConnectedClient):
    """Details of a client connected to an Omada device."""

    @property
    def device_category(self) -> str | None:
        """Device category."""
        return self._data.get("deviceCategory")

    @property
    def ip_setting(self) -> IpSetting:
        """IP Reservation settings of client."""
        return IpSetting(self._data["ipSetting"])

    @property
    def os_name(self) -> str | None:
        """Operating system name."""
        return self._data.get("osName")

    @property
    def rate_limit(self) -> RateLimit:
        """Rate limit settings of client."""
        return RateLimit(self._data["rateLimit"])

    @property
    def vendor(self) -> str | None:
        """Vendor of the device."""
        return self._data.get("vendor")


class OmadaWiredClient(OmadaConnectedClient):
    """Details of a wired connected client."""

    @property
    def dot1x_vlan(self) -> int:
        """Network name corresponding to the VLAN obtained by 802.1x D-VLAN"""
        return self._data.get("dot1xVlan", 0)

    @property
    def gateway_mac(self) -> str | None:
        """Mac address of gateway the client is connected to"""
        return self._data.get("switchMac")

    @property
    def gateway_name(self) -> str | None:
        """Name of gateway the client is connected to"""
        return self._data.get("gatewayName")

    @property
    def network_name(self) -> str:
        """Network name"""
        return self._data["networkName"]

    @property
    def port(self) -> int:
        """Switch port client is connected to"""
        return self._data.get("port", -1)

    @property
    def switch_mac(self) -> str | None:
        """Mac address of switch the client is connected to"""
        return self._data.get("switchMac")

    @property
    def switch_name(self) -> str | None:
        """Name of switch the client is connected to"""
        return self._data.get("switchName")


class OmadaWiredClientDetails(OmadaWiredClient, OmadaClientDetails):
    """Details of a wired connected client."""


class OmadaWirelessClient(OmadaConnectedClient):
    """Details of a wireless connected client."""

    @property
    def ap_mac(self) -> str:
        """Access point mac address"""
        return self._data["apMac"]

    @property
    def ap_name(self) -> str:
        """Access point name"""
        return self._data["apName"]

    @property
    def channel(self) -> int:
        """WiFi channel number."""
        return self._data["channel"]

    @property
    def is_power_save(self) -> bool:
        """Indicates if power save mode is enabled"""
        return self._data["powerSave"]

    @property
    def radio_id(self) -> RadioId:
        """Radio frequency id"""
        return RadioId(self._data["radioId"])

    @property
    def rssi(self) -> int:
        """Signal strength in dBm"""
        return self._data["rssi"]

    @property
    def rx_rate(self) -> int:
        """Uplink negotiation rate in Kbit/s"""
        return self._data["rxRate"]

    @property
    def signal_level(self) -> int:
        """Signal strength percentage"""
        return self._data["signalLevel"]

    @property
    def signal_rank(self) -> int:
        """Signal strength (0-5)"""
        return self._data["signalRank"]

    @property
    def ssid(self) -> str:
        """SSID name"""
        return self._data["ssid"]

    @property
    def tx_rate(self) -> int:
        """Downlink negotiation rate (Kbit/s)"""
        return self._data["txRate"]

    @property
    def wifi_mode(self) -> WifiMode:
        """WiFi mode"""
        return WifiMode(self._data["wifiMode"])


class OmadaWirelessClientDetails(OmadaWirelessClient, OmadaClientDetails):
    """Details of an Omada Wireless Client."""
