"""
Z21 LAN Protocol Headers and X-Headers
Extracted from Z21 LAN Protocol Specification v1.13 (06.11.2023)
"""

# =============================================================================
# LAN Headers (2 bytes, little-endian)
# =============================================================================

LAN_GET_SERIAL_NUMBER = 0x10
LAN_GET_CODE = 0x18
LAN_GET_HWINFO = 0x1A
LAN_LOGOFF = 0x30
LAN_DISCOVER_DEVICES = 0x35
LAN_X = 0x40  # X-BUS tunneling header
LAN_SET_BROADCASTFLAGS = 0x50
LAN_GET_BROADCASTFLAGS = 0x51
LAN_GET_LOCOMODE = 0x60
LAN_SET_LOCOMODE = 0x61
LAN_GET_TURNOUTMODE = 0x70
LAN_SET_TURNOUTMODE = 0x71
LAN_RMBUS_DATACHANGED = 0x80
LAN_RMBUS_GETDATA = 0x81
LAN_RMBUS_PROGRAMMODULE = 0x82
LAN_SYSTEMSTATE_DATACHANGED = 0x84
LAN_SYSTEMSTATE_GETDATA = 0x85
LAN_RAILCOM_DATACHANGED = 0x88
LAN_RAILCOM_GETDATA = 0x89
LAN_LOCONET_Z21_RX = 0xA0
LAN_LOCONET_Z21_TX = 0xA1
LAN_LOCONET_FROM_LAN = 0xA2
LAN_LOCONET_DISPATCH_ADDR = 0xA3
LAN_LOCONET_DETECTOR = 0xA4
LAN_BOOSTER_SET_POWER = 0xB2
LAN_BOOSTER_GET_DESCRIPTION = 0xB8
LAN_BOOSTER_SET_DESCRIPTION = 0xB9
LAN_BOOSTER_SYSTEMSTATE_DATACHANGED = 0xBA
LAN_BOOSTER_SYSTEMSTATE_GETDATA = 0xBB
LAN_CAN_DETECTOR = 0xC4
LAN_CAN_DEVICE_GET_DESCRIPTION = 0xC8
LAN_CAN_DEVICE_SET_DESCRIPTION = 0xC9
LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD = 0xCA
LAN_CAN_BOOSTER_SET_TRACKPOWER = 0xCB
LAN_FAST_CLOCK_CONTROL = 0xCC
LAN_FAST_CLOCK_DATA = 0xCD
LAN_FAST_CLOCK_SETTINGS_GET = 0xCE
LAN_FAST_CLOCK_SETTINGS_SET = 0xCF
LAN_DECODER_GET_DESCRIPTION = 0xD8
LAN_DECODER_SET_DESCRIPTION = 0xD9
LAN_DECODER_SYSTEMSTATE_DATACHANGED = 0xDA
LAN_DECODER_SYSTEMSTATE_GETDATA = 0xDB
LAN_ZLINK_GET_HWINFO = 0xE8

# =============================================================================
# X-Headers (used with LAN_X header 0x40 for X-BUS tunneling)
# =============================================================================

# X-BUS version and status commands (0x21 with different DB0 values)
LAN_X_GET_VERSION = 0x21
LAN_X_GET_STATUS = 0x21
LAN_X_SET_TRACK_POWER_OFF = 0x21
LAN_X_SET_TRACK_POWER_ON = 0x21

# CV/Register read/write commands
LAN_X_DCC_READ_REGISTER = 0x22
LAN_X_CV_READ = 0x23
LAN_X_DCC_WRITE_REGISTER = 0x23
LAN_X_CV_WRITE = 0x24
LAN_X_MM_WRITE_BYTE = 0x24

# Turnout/Accessory commands
LAN_X_GET_TURNOUT_INFO = 0x43
LAN_X_TURNOUT_INFO = 0x43
LAN_X_GET_EXT_ACCESSORY_INFO = 0x44
LAN_X_EXT_ACCESSORY_INFO = 0x44
LAN_X_SET_TURNOUT = 0x53
LAN_X_SET_EXT_ACCESSORY = 0x54

# Broadcast messages (0x61 with different DB0 values)
LAN_X_BC_TRACK_POWER_OFF = 0x61
LAN_X_BC_TRACK_POWER_ON = 0x61
LAN_X_BC_PROGRAMMING_MODE = 0x61
LAN_X_BC_TRACK_SHORT_CIRCUIT = 0x61
LAN_X_UNKNOWN_COMMAND = 0x61

# DB0 values distinguishing 0x61 broadcast sub-types
LAN_X_BC_TRACK_POWER_OFF_DB0 = 0x00
LAN_X_BC_TRACK_POWER_ON_DB0 = 0x01
LAN_X_BC_PROGRAMMING_MODE_DB0 = 0x02
LAN_X_BC_TRACK_SHORT_CIRCUIT_DB0 = 0x08

# Status and CV result
LAN_X_STATUS_CHANGED = 0x62
LAN_X_GET_VERSION_REPLY = 0x63
LAN_X_CV_RESULT = 0x64
LAN_X_CV_NACK_SC = 0x64
LAN_X_CV_NACK = 0x64

# Stop commands
LAN_X_SET_STOP = 0x80
LAN_X_BC_STOPPED = 0x81

# Loco emergency stop
LAN_X_SET_LOCO_E_STOP = 0x92

# Loco info and control
LAN_X_PURGE_LOCO = 0xE3
LAN_X_GET_LOCO_INFO = 0xE3
LAN_X_SET_LOCO_DRIVE = 0xE4
LAN_X_SET_LOCO_FUNCTION = 0xE4
LAN_X_SET_LOCO_FUNCTION_GROUP = 0xE4
LAN_X_SET_LOCO_BINARY_STATE = 0xE5

# POM (Programming on Main) commands
LAN_X_CV_POM_WRITE_BYTE = 0xE6
LAN_X_CV_POM_WRITE_BIT = 0xE6
LAN_X_CV_POM_READ_BYTE = 0xE6
LAN_X_CV_POM_ACCESSORY_WRITE_BYTE = 0xE6
LAN_X_CV_POM_ACCESSORY_WRITE_BIT = 0xE6
LAN_X_CV_POM_ACCESSORY_READ_BYTE = 0xE6

# Loco info reply
LAN_X_LOCO_INFO = 0xEF

# Firmware version
LAN_X_GET_FIRMWARE_VERSION = 0xF1
LAN_X_GET_FIRMWARE_VERSION_REPLY = 0xF3

# =============================================================================
# Header name lookup dictionary
# =============================================================================

HEADER_NAMES = {
    0x10: "LAN_GET_SERIAL_NUMBER",
    0x18: "LAN_GET_CODE",
    0x1A: "LAN_GET_HWINFO",
    0x30: "LAN_LOGOFF",
    0x35: "LAN_DISCOVER_DEVICES",
    0x40: "LAN_X",
    0x50: "LAN_SET_BROADCASTFLAGS",
    0x51: "LAN_GET_BROADCASTFLAGS",
    0x60: "LAN_GET_LOCOMODE",
    0x61: "LAN_SET_LOCOMODE",
    0x70: "LAN_GET_TURNOUTMODE",
    0x71: "LAN_SET_TURNOUTMODE",
    0x80: "LAN_RMBUS_DATACHANGED",
    0x81: "LAN_RMBUS_GETDATA",
    0x82: "LAN_RMBUS_PROGRAMMODULE",
    0x84: "LAN_SYSTEMSTATE_DATACHANGED",
    0x85: "LAN_SYSTEMSTATE_GETDATA",
    0x88: "LAN_RAILCOM_DATACHANGED",
    0x89: "LAN_RAILCOM_GETDATA",
    0xA0: "LAN_LOCONET_Z21_RX",
    0xA1: "LAN_LOCONET_Z21_TX",
    0xA2: "LAN_LOCONET_FROM_LAN",
    0xA3: "LAN_LOCONET_DISPATCH_ADDR",
    0xA4: "LAN_LOCONET_DETECTOR",
    0xB2: "LAN_BOOSTER_SET_POWER",
    0xB8: "LAN_BOOSTER_GET_DESCRIPTION",
    0xB9: "LAN_BOOSTER_SET_DESCRIPTION",
    0xBA: "LAN_BOOSTER_SYSTEMSTATE_DATACHANGED",
    0xBB: "LAN_BOOSTER_SYSTEMSTATE_GETDATA",
    0xC4: "LAN_CAN_DETECTOR",
    0xC8: "LAN_CAN_DEVICE_GET_DESCRIPTION",
    0xC9: "LAN_CAN_DEVICE_SET_DESCRIPTION",
    0xCA: "LAN_CAN_BOOSTER_SYSTEMSTATE_CHGD",
    0xCB: "LAN_CAN_BOOSTER_SET_TRACKPOWER",
    0xCC: "LAN_FAST_CLOCK_CONTROL",
    0xCD: "LAN_FAST_CLOCK_DATA",
    0xCE: "LAN_FAST_CLOCK_SETTINGS_GET",
    0xCF: "LAN_FAST_CLOCK_SETTINGS_SET",
    0xD8: "LAN_DECODER_GET_DESCRIPTION",
    0xD9: "LAN_DECODER_SET_DESCRIPTION",
    0xDA: "LAN_DECODER_SYSTEMSTATE_DATACHANGED",
    0xDB: "LAN_DECODER_SYSTEMSTATE_GETDATA",
    0xE8: "LAN_ZLINK_GET_HWINFO",
}

# =============================================================================
# X-Header name lookup dictionary
# Note: Many X-Headers share the same hex value but differ by DB0 byte
# =============================================================================

X_HEADER_NAMES = {
    0x21: "LAN_X_GET_VERSION/LAN_X_GET_STATUS/LAN_X_SET_TRACK_POWER",
    0x22: "LAN_X_DCC_READ_REGISTER",
    0x23: "LAN_X_CV_READ/LAN_X_DCC_WRITE_REGISTER",
    0x24: "LAN_X_CV_WRITE/LAN_X_MM_WRITE_BYTE",
    0x43: "LAN_X_GET_TURNOUT_INFO/LAN_X_TURNOUT_INFO",
    0x44: "LAN_X_GET_EXT_ACCESSORY_INFO/LAN_X_EXT_ACCESSORY_INFO",
    0x53: "LAN_X_SET_TURNOUT",
    0x54: "LAN_X_SET_EXT_ACCESSORY",
    0x61: "LAN_X_BC_TRACK_POWER/LAN_X_UNKNOWN_COMMAND",
    0x62: "LAN_X_STATUS_CHANGED",
    0x63: "LAN_X_GET_VERSION_REPLY",
    0x64: "LAN_X_CV_RESULT/LAN_X_CV_NACK",
    0x80: "LAN_X_SET_STOP",
    0x81: "LAN_X_BC_STOPPED",
    0x92: "LAN_X_SET_LOCO_E_STOP",
    0xE3: "LAN_X_PURGE_LOCO/LAN_X_GET_LOCO_INFO",
    0xE4: "LAN_X_SET_LOCO_DRIVE/LAN_X_SET_LOCO_FUNCTION",
    0xE5: "LAN_X_SET_LOCO_BINARY_STATE",
    0xE6: "LAN_X_CV_POM",
    0xEF: "LAN_X_LOCO_INFO",
    0xF1: "LAN_X_GET_FIRMWARE_VERSION",
    0xF3: "LAN_X_GET_FIRMWARE_VERSION_REPLY",
}

def get_x_header_name(x_header: int) -> str:
    """Get the name of an X-Header by its hex value."""
    return X_HEADER_NAMES.get(x_header, f"UNKNOWN_HEADER_0x{x_header:02X}")

def get_header_name(header: int) -> str:
    """Get the name of a LAN header by its hex value."""
    return HEADER_NAMES.get(header, get_x_header_name(header))


