"""Protocol Interfaces Functional Domain"""

import zigpy.types as t
from zigpy.zcl import Cluster


class DateTime(t.Struct):
    _fields = [
        ('date', t.uint32_t),
        ('time', t.uint32_t),
    ]


class GenericTunnel(Cluster):
    cluster_id = 0x0600
    ep_attribute = 'generic_tunnel'
    attributes = {
        0x0001: ('max_income_trans_size', t.uint16_t),
        0x0002: ('max_outgo_trans_size', t.uint16_t),
        0x0003: ('protocol_addr', t.LVBytes),
    }
    server_commands = {
        0x0000: ('match_protocol_addr', (), False),
    }
    client_commands = {
        0x0000: ('match_protocol_addr_response', (), True),
        0x0001: ('advertise_protocol_address', (), False),
    }


class BacnetProtocolTunnel(Cluster):
    cluster_id = 0x0601
    ep_attribute = 'bacnet_tunnel'
    attributes = {}
    server_commands = {
        0x0000: ('transfer_npdu', (t.LVBytes, ), False),
    }
    client_commands = {}


class AnalogInputRegular(Cluster):
    cluster_id = 0x0602
    ep_attribute = 'bacnet_regular_analog_input'
    attributes = {
        0x0016: ('cov_increment', t.Single),
        0x001f: ('device_type', t.CharacterString),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x0076: ('update_interval', t.uint8_t),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class AnalogInputExtended(Cluster):
    cluster_id = 0x0603
    ep_attribute = 'bacnet_extended_analog_input'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0011: ('notification_class', t.uint16_t),
        0x0019: ('deadband', t.Single),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x002d: ('high_limit', t.Single),
        0x0034: ('limit_enable', t.bitmap8),
        0x003b: ('low_limit', t.Single),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {
        0x0000: ('transfer_apdu', (), False),
        0x0001: ('connect_req', (), False),
        0x0002: ('disconnect_req', (), False),
        0x0003: ('connect_status_noti', (), False),
    }
    client_commands = {}


class AnalogOutputRegular(Cluster):
    cluster_id = 0x0604
    ep_attribute = 'bacnet_regular_analog_output'
    attributes = {
        0x0016: ('cov_increment', t.Single),
        0x001f: ('device_type', t.CharacterString),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x0076: ('update_interval', t.uint8_t),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class AnalogOutputExtended(Cluster):
    cluster_id = 0x0605
    ep_attribute = 'bacnet_extended_analog_output'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0011: ('notification_class', t.uint16_t),
        0x0019: ('deadband', t.Single),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x002d: ('high_limit', t.Single),
        0x0034: ('limit_enable', t.bitmap8),
        0x003b: ('low_limit', t.Single),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class AnalogValueRegular(Cluster):
    cluster_id = 0x0606
    ep_attribute = 'bacnet_regular_analog_value'
    attributes = {
        0x0016: ('cov_increment', t.Single),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class AnalogValueExtended(Cluster):
    cluster_id = 0x0607
    ep_attribute = 'bacnet_extended_analog_value'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0011: ('notification_class', t.uint16_t),
        0x0019: ('deadband', t.Single),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x002d: ('high_limit', t.Single),
        0x0034: ('limit_enable', t.bitmap8),
        0x003b: ('low_limit', t.Single),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class BinaryInputRegular(Cluster):
    cluster_id = 0x0608
    ep_attribute = 'bacnet_regular_binary_input'
    attributes = {
        0x000f: ('change_of_state_count', t.uint32_t),
        0x0010: ('change_of_state_time', DateTime),
        0x001f: ('device_type', t.CharacterString),
        0x0021: ('elapsed_active_time', t.uint32_t),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x0072: ('time_of_at_reset', DateTime),
        0x0073: ('time_of_sc_reset', DateTime),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class BinaryInputExtended(Cluster):
    cluster_id = 0x0609
    ep_attribute = 'bacnet_extended_binary_input'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0006: ('alarm_value', t.Bool),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class BinaryOutputRegular(Cluster):
    cluster_id = 0x060a
    ep_attribute = 'bacnet_regular_binary_output'
    attributes = {
        0x000f: ('change_of_state_count', t.uint32_t),
        0x0010: ('change_of_state_time', DateTime),
        0x001f: ('device_type', t.CharacterString),
        0x0021: ('elapsed_active_time', t.uint32_t),
        0x0028: ('feed_back_value', t.enum8),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x0072: ('time_of_at_reset', DateTime),
        0x0073: ('time_of_sc_reset', DateTime),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class BinaryOutputExtended(Cluster):
    cluster_id = 0x060b
    ep_attribute = 'bacnet_extended_binary_output'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class BinaryValueRegular(Cluster):
    cluster_id = 0x060c
    ep_attribute = 'bacnet_regular_binary_value'
    attributes = {
        0x000f: ('change_of_state_count', t.uint32_t),
        0x0010: ('change_of_state_time', DateTime),
        0x0021: ('elapsed_active_time', t.uint32_t),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x0072: ('time_of_at_reset', DateTime),
        0x0073: ('time_of_sc_reset', DateTime),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class BinaryValueExtended(Cluster):
    cluster_id = 0x060d
    ep_attribute = 'bacnet_extended_binary_value'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0006: ('alarm_value', t.Bool),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class MultistateInputRegular(Cluster):
    cluster_id = 0x060e
    ep_attribute = 'bacnet_regular_multistate_input'
    attributes = {
        0x001f: ('device_type', t.CharacterString),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class MultistateInputExtended(Cluster):
    cluster_id = 0x060f
    ep_attribute = 'bacnet_extended_multistate_input'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0006: ('alarm_value', t.uint16_t),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0025: ('fault_values', t.uint16_t),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class MultistateOutputRegular(Cluster):
    cluster_id = 0x0610
    ep_attribute = 'bacnet_regular_multistate_output'
    attributes = {
        0x001f: ('device_type', t.CharacterString),
        0x0028: ('feed_back_value', t.enum8),
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class MultistateOutputExtended(Cluster):
    cluster_id = 0x0611
    ep_attribute = 'bacnet_extended_multistate_output'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}


class MultistateValueRegular(Cluster):
    cluster_id = 0x0612
    ep_attribute = 'bacnet_regular_multistate_value'
    attributes = {
        0x004b: ('object_id', t.fixed_list(4, t.uint8_t)),
        0x004d: ('object_name', t.CharacterString),
        0x004f: ('object_type', t.enum16),
        0x00a8: ('profile_name', t.CharacterString),
    }
    server_commands = {}
    client_commands = {}


class MultistateValueExtended(Cluster):
    cluster_id = 0x0613
    ep_attribute = 'bacnet_extended_multistate_value'
    attributes = {
        0x0000: ('acked_transitions', t.bitmap8),
        0x0006: ('alarm_value', t.uint16_t),
        0x0011: ('notification_class', t.uint16_t),
        0x0023: ('event_enable', t.bitmap8),
        0x0024: ('event_state', t.enum8),
        0x0025: ('fault_values', t.uint16_t),
        0x0048: ('notify_type', t.enum8),
        0x0071: ('time_delay', t.uint8_t),
        # 0x0082: ('event_time_stamps', TODO.array),  # Array[3] of (16-bit unsigned integer, time of day, or structure of (date, time of day))
    }
    server_commands = {}
    client_commands = {}
