"""Test the Z-Wave JS humidifier platform."""
from zwave_js_server.const import CommandClass
from zwave_js_server.const.command_class.humidity_control import HumidityControlMode
from zwave_js_server.event import Event

from homeassistant.components.humidifier import HumidifierDeviceClass
from homeassistant.components.humidifier.const import (
    ATTR_HUMIDITY,
    ATTR_MAX_HUMIDITY,
    ATTR_MIN_HUMIDITY,
    DEFAULT_MAX_HUMIDITY,
    DEFAULT_MIN_HUMIDITY,
    DOMAIN as HUMIDIFIER_DOMAIN,
    SERVICE_SET_HUMIDITY,
)
from homeassistant.const import (
    ATTR_DEVICE_CLASS,
    ATTR_ENTITY_ID,
    SERVICE_TURN_OFF,
    SERVICE_TURN_ON,
    STATE_OFF,
    STATE_ON,
)

from .common import DEHUMIDIFIER_ADC_T3000_ENTITY, HUMIDIFIER_ADC_T3000_ENTITY


async def test_humidifier(hass, client, climate_adc_t3000, integration):
    """Test a humidity control command class entity."""

    node = climate_adc_t3000
    state = hass.states.get(HUMIDIFIER_ADC_T3000_ENTITY)

    assert state
    assert state.state == STATE_ON
    assert state.attributes[ATTR_DEVICE_CLASS] == HumidifierDeviceClass.HUMIDIFIER
    assert state.attributes[ATTR_HUMIDITY] == 35
    assert state.attributes[ATTR_MIN_HUMIDITY] == 10
    assert state.attributes[ATTR_MAX_HUMIDITY] == 70

    client.async_send_command.reset_mock()

    # Test setting humidity
    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_SET_HUMIDITY,
        {
            ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY,
            ATTR_HUMIDITY: 41,
        },
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 1,
        "commandClassName": "Humidity Control Setpoint",
        "commandClass": CommandClass.HUMIDITY_CONTROL_SETPOINT,
        "endpoint": 0,
        "property": "setpoint",
        "propertyKey": 1,
        "propertyName": "setpoint",
        "propertyKeyName": "Humidifier",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "unit": "%",
            "min": 10,
            "max": 70,
            "ccSpecific": {"setpointType": 1},
        },
        "value": 35,
    }
    assert args["value"] == 41

    client.async_send_command.reset_mock()

    # Test de-humidify mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.DEHUMIDIFY),
                "prevValue": int(HumidityControlMode.HUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(HUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_OFF

    client.async_send_command.reset_mock()

    # Test auto mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.HUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(HUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_ON

    client.async_send_command.reset_mock()

    # Test off mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.HUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(HUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_OFF

    client.async_send_command.reset_mock()

    # Test turning off when device is previously humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.HUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.HUMIDIFY),
    }
    assert args["value"] == int(HumidityControlMode.OFF)

    client.async_send_command.reset_mock()

    # Test turning off when device is previously auto
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.AUTO),
    }
    assert args["value"] == int(HumidityControlMode.DEHUMIDIFY)

    client.async_send_command.reset_mock()

    # Test turning off when device is previously de-humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.DEHUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning off when device is previously off
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.AUTO),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.HUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously auto
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously de-humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.DEHUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.DEHUMIDIFY),
    }
    assert args["value"] == int(HumidityControlMode.AUTO)

    client.async_send_command.reset_mock()

    # Test turning on when device is previously off
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.AUTO),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: HUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.OFF),
    }
    assert args["value"] == int(HumidityControlMode.HUMIDIFY)


async def test_dehumidifier_missing_setpoint(
    hass, client, climate_adc_t3000_missing_setpoint, integration
):
    """Test a humidity control command class entity."""

    entity_id = "humidifier.adc_t3000_missing_setpoint_dehumidifier"
    state = hass.states.get(entity_id)

    assert state
    assert ATTR_HUMIDITY not in state.attributes
    assert state.attributes[ATTR_MIN_HUMIDITY] == DEFAULT_MIN_HUMIDITY
    assert state.attributes[ATTR_MAX_HUMIDITY] == DEFAULT_MAX_HUMIDITY

    client.async_send_command.reset_mock()

    # Test setting humidity
    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_SET_HUMIDITY,
        {
            ATTR_ENTITY_ID: entity_id,
            ATTR_HUMIDITY: 41,
        },
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()


async def test_humidifier_missing_mode(
    hass, client, climate_adc_t3000_missing_mode, integration
):
    """Test a humidity control command class entity."""

    node = climate_adc_t3000_missing_mode

    # Test that de-humidifer entity does not exist but humidifier entity does
    entity_id = "humidifier.adc_t3000_missing_mode_dehumidifier"
    state = hass.states.get(entity_id)
    assert not state

    entity_id = "humidifier.adc_t3000_missing_mode_humidifier"
    state = hass.states.get(entity_id)
    assert state

    client.async_send_command.reset_mock()

    # Test turning off when device is previously auto for a device which does not have de-humidify mode
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: entity_id},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.AUTO),
    }
    assert args["value"] == int(HumidityControlMode.OFF)

    client.async_send_command.reset_mock()


async def test_dehumidifier(hass, client, climate_adc_t3000, integration):
    """Test a humidity control command class entity."""

    node = climate_adc_t3000
    state = hass.states.get(DEHUMIDIFIER_ADC_T3000_ENTITY)

    assert state
    assert state.state == STATE_ON
    assert state.attributes[ATTR_DEVICE_CLASS] == HumidifierDeviceClass.DEHUMIDIFIER
    assert state.attributes[ATTR_HUMIDITY] == 60
    assert state.attributes[ATTR_MIN_HUMIDITY] == 30
    assert state.attributes[ATTR_MAX_HUMIDITY] == 90

    client.async_send_command.reset_mock()

    # Test setting humidity
    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_SET_HUMIDITY,
        {
            ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY,
            ATTR_HUMIDITY: 41,
        },
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 1,
        "commandClassName": "Humidity Control Setpoint",
        "commandClass": CommandClass.HUMIDITY_CONTROL_SETPOINT,
        "endpoint": 0,
        "property": "setpoint",
        "propertyKey": 2,
        "propertyName": "setpoint",
        "propertyKeyName": "De-humidifier",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "unit": "%",
            "min": 30,
            "max": 90,
            "ccSpecific": {"setpointType": 2},
        },
        "value": 60,
    }
    assert args["value"] == 41

    client.async_send_command.reset_mock()

    # Test humidify mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.HUMIDIFY),
                "prevValue": int(HumidityControlMode.DEHUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(DEHUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_OFF

    client.async_send_command.reset_mock()

    # Test auto mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.DEHUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(DEHUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_ON

    client.async_send_command.reset_mock()

    # Test off mode update from value updated event
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.DEHUMIDIFY),
            },
        },
    )
    node.receive_event(event)

    state = hass.states.get(DEHUMIDIFIER_ADC_T3000_ENTITY)
    assert state.state == STATE_OFF

    client.async_send_command.reset_mock()

    # Test turning off when device is previously de-humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.DEHUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.DEHUMIDIFY),
    }
    assert args["value"] == int(HumidityControlMode.OFF)

    client.async_send_command.reset_mock()

    # Test turning off when device is previously auto
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.AUTO),
    }
    assert args["value"] == int(HumidityControlMode.HUMIDIFY)

    client.async_send_command.reset_mock()

    # Test turning off when device is previously humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.HUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning off when device is previously off
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.AUTO),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_OFF,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously de-humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.DEHUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously auto
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.AUTO),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 0

    client.async_send_command.reset_mock()

    # Test turning on when device is previously humidifying
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.HUMIDIFY),
                "prevValue": int(HumidityControlMode.OFF),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.HUMIDIFY),
    }
    assert args["value"] == int(HumidityControlMode.AUTO)

    client.async_send_command.reset_mock()

    # Test turning on when device is previously off
    event = Event(
        type="value updated",
        data={
            "source": "node",
            "event": "value updated",
            "nodeId": 68,
            "args": {
                "commandClassName": "Humidity Control Mode",
                "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
                "endpoint": 0,
                "property": "mode",
                "propertyName": "mode",
                "newValue": int(HumidityControlMode.OFF),
                "prevValue": int(HumidityControlMode.AUTO),
            },
        },
    )
    node.receive_event(event)

    await hass.services.async_call(
        HUMIDIFIER_DOMAIN,
        SERVICE_TURN_ON,
        {ATTR_ENTITY_ID: DEHUMIDIFIER_ADC_T3000_ENTITY},
        blocking=True,
    )

    assert len(client.async_send_command.call_args_list) == 1
    args = client.async_send_command.call_args_list[0][0][0]
    assert args["command"] == "node.set_value"
    assert args["nodeId"] == 68
    assert args["valueId"] == {
        "ccVersion": 2,
        "commandClassName": "Humidity Control Mode",
        "commandClass": CommandClass.HUMIDITY_CONTROL_MODE,
        "endpoint": 0,
        "property": "mode",
        "propertyName": "mode",
        "metadata": {
            "type": "number",
            "readable": True,
            "writeable": True,
            "min": 0,
            "max": 255,
            "label": "Humidity control mode",
            "states": {"0": "Off", "1": "Humidify", "2": "De-humidify", "3": "Auto"},
        },
        "value": int(HumidityControlMode.OFF),
    }
    assert args["value"] == int(HumidityControlMode.DEHUMIDIFY)