import sys

CMD_SOH = chr(0x01)
CMD_STX = chr(0x02)
CMD_ETX = chr(0x03)
CMD_EOT = chr(0x04)

CMD_ACK = chr(0x00)
CMD_ERR_CMD = chr(0x01)
CMD_ERR_CHKS = chr(0x02)
CMD_ERR_FORM = chr(0x03)
CMD_ERR_DATA = chr(0x04)
CMD_ERR_TOUT = chr(0x05)
CMD_ERR_ADDR = chr(0x06)
CMD_ERR_TIME = chr(0x07)
CMD_ERR_FRAME_SIZE = chr(0x08)
CMD_ERR_DATA_TYPE = chr(0x09)
CMD_ERR_PORT_TYPE = chr(0x0A)
CMD_ERR_PORT_NUMBER = chr(0x0B)
CMD_ERR_DATA_SIZE = chr(0x0C)

CMD_EXT_INQUIRY = chr(0x41)
CMD_EXT_RESET = chr(0x42)
CMD_EXT_VERSION = chr(0x43)
CMD_EXT_SAVE = chr(0x44)
CMD_EXT_RESTORE = chr(0x45)
CMD_EXT_GET_ADDR = chr(0x46)
CMD_EXT_SET_ADDR = chr(0x47)
CMD_EXT_GET_TIME = chr(0x48)
CMD_EXT_SET_TIME = chr(0x49)
CMD_EXT_GET_FRAME = chr(0x4A)
CMD_EXT_SET_FRAME = chr(0x4B)
CMD_EXT_GET_PORT = chr(0x4C)
CMD_EXT_SET_PORT = chr(0x4D)
CMD_EXT_GET_DATA = chr(0x4E)
CMD_EXT_SET_DATA = chr(0x4F)

CMD_EXT_NO_PARAMS = [
    CMD_EXT_INQUIRY,
    CMD_EXT_RESET,
    CMD_EXT_VERSION,
    CMD_EXT_SAVE,
    CMD_EXT_RESTORE,
    CMD_EXT_GET_ADDR,
    CMD_EXT_GET_TIME,
    CMD_EXT_GET_FRAME
]

CMD_EXT_WITH_PARAMS = [
    CMD_EXT_SET_ADDR,
    CMD_EXT_SET_TIME,
    CMD_EXT_SET_FRAME,
    CMD_EXT_GET_PORT,
    CMD_EXT_SET_PORT,
    CMD_EXT_GET_DATA,
    CMD_EXT_SET_DATA
]

CMD_EXT = []
CMD_EXT += CMD_EXT_NO_PARAMS + CMD_EXT_WITH_PARAMS

CMD_ABBR_INQUIRY = chr(0x61)
CMD_ABBR_RESET = chr(0x62)
CMD_ABBR_VERSION = chr(0x63)
CMD_ABBR_SAVE = chr(0x64)
CMD_ABBR_RESTORE = chr(0x65)
CMD_ABBR_GET_ADDR = chr(0x66)
CMD_ABBR_SET_ADDR = chr(0x67)
CMD_ABBR_GET_TIME = chr(0x68)
CMD_ABBR_SET_TIME = chr(0x69)
CMD_ABBR_GET_FRAME = chr(0x6A)
CMD_ABBR_SET_FRAME = chr(0x6B)
CMD_ABBR_GET_PORT = chr(0x6C)
CMD_ABBR_SET_PORT = chr(0x6D)
CMD_ABBR_GET_DATA = chr(0x6E)
CMD_ABBR_SET_DATA = chr(0x6F)

CMD_ABBR_NO_PARAMS = [
    CMD_ABBR_INQUIRY,
    CMD_ABBR_RESET,
    CMD_ABBR_VERSION,
    CMD_ABBR_SAVE,
    CMD_ABBR_RESTORE,
    CMD_ABBR_GET_ADDR,
    CMD_ABBR_GET_TIME,
    CMD_ABBR_GET_FRAME
]

CMD_ABBR_WITH_PARAMS = [
    CMD_ABBR_SET_ADDR,
    CMD_ABBR_SET_TIME,
    CMD_ABBR_SET_FRAME,
    CMD_ABBR_GET_PORT,
    CMD_ABBR_SET_PORT,
    CMD_ABBR_GET_DATA,
    CMD_ABBR_SET_DATA
]

CMD_ABBR = []
CMD_ABBR += CMD_ABBR_NO_PARAMS + CMD_ABBR_WITH_PARAMS

CMD_INQUIRY = [CMD_EXT_INQUIRY, CMD_ABBR_INQUIRY]
CMD_RESET = [CMD_EXT_RESET, CMD_ABBR_RESET]
CMD_VERSION = [CMD_EXT_VERSION, CMD_ABBR_VERSION]
CMD_SAVE = [CMD_EXT_SAVE, CMD_ABBR_SAVE]
CMD_RESTORE = [CMD_EXT_RESTORE, CMD_ABBR_RESTORE]
CMD_GET_ADDR = [CMD_EXT_GET_ADDR, CMD_ABBR_GET_ADDR]
CMD_SET_ADDR = [CMD_EXT_SET_ADDR, CMD_ABBR_SET_ADDR]
CMD_GET_TIME = [CMD_EXT_GET_TIME, CMD_ABBR_GET_TIME]
CMD_SET_TIME = [CMD_EXT_SET_TIME, CMD_ABBR_SET_TIME]
CMD_GET_FRAME = [CMD_EXT_GET_FRAME, CMD_ABBR_GET_FRAME]
CMD_SET_FRAME = [CMD_EXT_SET_FRAME, CMD_ABBR_SET_FRAME]
CMD_GET_PORT = [CMD_EXT_GET_PORT, CMD_ABBR_GET_PORT]
CMD_SET_PORT = [CMD_EXT_SET_PORT, CMD_ABBR_SET_PORT]
CMD_GET_DATA = [CMD_EXT_GET_DATA, CMD_ABBR_GET_DATA]
CMD_SET_DATA = [CMD_EXT_SET_DATA, CMD_ABBR_SET_DATA]

ACCEPTED_COMMANDS = []
ACCEPTED_COMMANDS += CMD_EXT_NO_PARAMS
ACCEPTED_COMMANDS += CMD_EXT_WITH_PARAMS
ACCEPTED_COMMANDS += CMD_ABBR_NO_PARAMS
ACCEPTED_COMMANDS += CMD_ABBR_WITH_PARAMS

SLAVE_ADDR_BROADCAST_NO_ANSWER = chr(0x00)
SLAVE_ADDR_BROADCAST_WITH_ANSWER = chr(0x7F)
SLAVE_ADDR_BROADCAST = [
    SLAVE_ADDR_BROADCAST_NO_ANSWER,
    SLAVE_ADDR_BROADCAST_WITH_ANSWER
]
SLAVE_ADDR_ACCEPTED = [chr(addr) for addr in range(0x01, 0x7F)]
SLAVE_ADDRESSES = SLAVE_ADDR_ACCEPTED + SLAVE_ADDR_BROADCAST

MASTER_ADDRESSES = [chr(addr) for addr in range(0x01, 0x7F)]
PROGRESSIVE_IDS = [chr(addr) for addr in range(0x00, 0x80)]

FRAME_SIZE_ACCEPTED = [chr(addr) for addr in range(0x01, 0x7F)]

# Index of the byte that stores the command code
SLAVE_IDX = 1
MASTER_IDX = 2
CMD_IDX = 3
ID_IDX = 4
PAR_LEN_IDX = 5
PAR_LIST_IDX = 6
CHECKSUM_IDX = -2

AD24_LEN = 8

VERSION = '\x00' * 8  # Dummy version

# Data types
DATA_TYPE_STRING = chr(0x00)
DATA_TYPE_CHAR = chr(0x01)
DATA_TYPE_STRUCT = chr(0x02)
DATA_TYPE_B01 = chr(0x03)
DATA_TYPE_B08 = chr(0x04)
DATA_TYPE_B16 = chr(0x05)
DATA_TYPE_B32 = chr(0x06)
DATA_TYPE_B64 = chr(0x07)
DATA_TYPE_U08 = chr(0x08)
DATA_TYPE_S08 = chr(0x09)
DATA_TYPE_H08 = chr(0x0A)
DATA_TYPE_O08 = chr(0x0B)
DATA_TYPE_U16 = chr(0x0C)
DATA_TYPE_S16 = chr(0x0D)
DATA_TYPE_H16 = chr(0x0E)
DATA_TYPE_O16 = chr(0x0F)
DATA_TYPE_U32 = chr(0x10)
DATA_TYPE_S32 = chr(0x11)
DATA_TYPE_H32 = chr(0x12)
DATA_TYPE_O32 = chr(0x13)
DATA_TYPE_U64 = chr(0x14)
DATA_TYPE_S64 = chr(0x15)
DATA_TYPE_H64 = chr(0x16)
DATA_TYPE_O64 = chr(0x17)
DATA_TYPE_F32 = chr(0x18)
DATA_TYPE_F64 = chr(0x19)
DATA_TYPE_PTR = chr(0x1A)

DATA_TYPE_7STRING = chr(0x20)
DATA_TYPE_7CHAR = chr(0x21)
DATA_TYPE_7STRUCT = chr(0x22)
DATA_TYPE_7B01 = chr(0x23)
DATA_TYPE_7B08 = chr(0x24)
DATA_TYPE_7B16 = chr(0x25)
DATA_TYPE_7B32 = chr(0x26)
DATA_TYPE_7B64 = chr(0x27)
DATA_TYPE_7U08 = chr(0x28)
DATA_TYPE_7S08 = chr(0x29)
DATA_TYPE_7H08 = chr(0x2A)
DATA_TYPE_7O08 = chr(0x2B)
DATA_TYPE_7U16 = chr(0x2C)
DATA_TYPE_7S16 = chr(0x2D)
DATA_TYPE_7H16 = chr(0x2E)
DATA_TYPE_7O16 = chr(0x2F)
DATA_TYPE_7U32 = chr(0x30)
DATA_TYPE_7S32 = chr(0x31)
DATA_TYPE_7H32 = chr(0x32)
DATA_TYPE_7O32 = chr(0x33)
DATA_TYPE_7U64 = chr(0x34)
DATA_TYPE_7S64 = chr(0x35)
DATA_TYPE_7H64 = chr(0x36)
DATA_TYPE_7O64 = chr(0x37)
DATA_TYPE_7F32 = chr(0x38)
DATA_TYPE_7F64 = chr(0x39)

DATA_TYPE_TIME = chr(0x40)

DATA_TYPES = [
    DATA_TYPE_STRING,
    DATA_TYPE_CHAR,
    DATA_TYPE_STRUCT,
    DATA_TYPE_B01,
    DATA_TYPE_B08,
    DATA_TYPE_B16,
    DATA_TYPE_B32,
    DATA_TYPE_B64,
    DATA_TYPE_U08,
    DATA_TYPE_S08,
    DATA_TYPE_H08,
    DATA_TYPE_O08,
    DATA_TYPE_U16,
    DATA_TYPE_S16,
    DATA_TYPE_H16,
    DATA_TYPE_O16,
    DATA_TYPE_U32,
    DATA_TYPE_S32,
    DATA_TYPE_H32,
    DATA_TYPE_O32,
    DATA_TYPE_U64,
    DATA_TYPE_S64,
    DATA_TYPE_H64,
    DATA_TYPE_O64,
    DATA_TYPE_F32,
    DATA_TYPE_F64,
    DATA_TYPE_PTR,
    DATA_TYPE_7STRING,
    DATA_TYPE_7CHAR,
    DATA_TYPE_7STRUCT,
    DATA_TYPE_7B01,
    DATA_TYPE_7B08,
    DATA_TYPE_7B16,
    DATA_TYPE_7B32,
    DATA_TYPE_7B64,
    DATA_TYPE_7U08,
    DATA_TYPE_7S08,
    DATA_TYPE_7H08,
    DATA_TYPE_7O08,
    DATA_TYPE_7U16,
    DATA_TYPE_7S16,
    DATA_TYPE_7H16,
    DATA_TYPE_7O16,
    DATA_TYPE_7U32,
    DATA_TYPE_7S32,
    DATA_TYPE_7H32,
    DATA_TYPE_7O32,
    DATA_TYPE_7U64,
    DATA_TYPE_7S64,
    DATA_TYPE_7H64,
    DATA_TYPE_7O64,
    DATA_TYPE_7F32,
    DATA_TYPE_7F64,
    DATA_TYPE_TIME
]

# Port types
PORT_TYPE_ALL = chr(0x00)
PORT_TYPE_SCI = chr(0x01)
PORT_TYPE_SPI = chr(0x02)
PORT_TYPE_IIC = chr(0x03)
PORT_TYPE_DIO = chr(0x04)
PORT_TYPE_AD = chr(0x05)
PORT_TYPE_DA = chr(0x06)
PORT_TYPE_CAN = chr(0x07)
PORT_TYPE_AD24 = chr(0x08)
PORT_TYPE_USER = chr(0x40)
PORT_TYPE_TEMP = chr(0x7A)
PORT_TYPE_PLD = chr(0x7B)
PORT_TYPE_EEP = chr(0x7C)
PORT_TYPE_RAM = chr(0x7D)
PORT_TYPE_ROM = chr(0x7E)
PORT_TYPE_CLK = chr(0x7F)

PORT_TYPES = [
    PORT_TYPE_ALL,
    PORT_TYPE_SCI,
    PORT_TYPE_SPI,
    PORT_TYPE_IIC,
    PORT_TYPE_DIO,
    PORT_TYPE_AD,
    PORT_TYPE_DA,
    PORT_TYPE_CAN,
    PORT_TYPE_AD24,
    PORT_TYPE_USER,
    PORT_TYPE_TEMP,
    PORT_TYPE_PLD,
    PORT_TYPE_EEP,
    PORT_TYPE_RAM,
    PORT_TYPE_ROM,
    PORT_TYPE_CLK
]

PORT_NUMBER_00 = '\x00'
PORT_NUMBER_01 = '\x01'
PORT_NUMBER_02 = '\x02'
PORT_NUMBER_03 = '\x03'
PORT_NUMBER_04 = '\x04'
PORT_NUMBER_05 = '\x05'
PORT_NUMBER_06 = '\x06'
PORT_NUMBER_07 = '\x07'
PORT_NUMBER_08 = '\x08'
PORT_NUMBER_09 = '\x09'
PORT_NUMBER_10 = '\x0A'
PORT_NUMBER_11 = '\x0B'
PORT_NUMBER_12 = '\x0C'
PORT_NUMBER_13 = '\x0D'
PORT_NUMBER_14 = '\x0E'
PORT_NUMBER_15 = '\x0F'
PORT_NUMBER_16 = '\x10'
PORT_NUMBER_17 = '\x11'
PORT_NUMBER_18 = '\x12'
PORT_NUMBER_19 = '\x13'
PORT_NUMBER_20 = '\x14'
PORT_NUMBER_21 = '\x15'
PORT_NUMBER_22 = '\x16'
PORT_NUMBER_23 = '\x17'
PORT_NUMBER_24 = '\x18'
PORT_NUMBER_25 = '\x19'
PORT_NUMBER_26 = '\x1A'
PORT_NUMBER_27 = '\x1B'
PORT_NUMBER_28 = '\x1C'
PORT_NUMBER_29 = '\x1D'
PORT_NUMBER_30 = '\x1E'
PORT_NUMBER_31 = '\x1F'
PORT_NUMBER_32 = '\x20'
PORT_NUMBER_33 = '\x21'
PORT_NUMBER_34 = '\x22'
PORT_NUMBER_35 = '\x23'
PORT_NUMBER_36 = '\x24'
PORT_NUMBER_37 = '\x25'
PORT_NUMBER_38 = '\x26'
PORT_NUMBER_39 = '\x27'
PORT_NUMBER_40 = '\x28'
PORT_NUMBER_41 = '\x29'
PORT_NUMBER_42 = '\x2A'
PORT_NUMBER_43 = '\x2B'
PORT_NUMBER_44 = '\x2C'
PORT_NUMBER_45 = '\x2D'
PORT_NUMBER_46 = '\x2E'
PORT_NUMBER_47 = '\x2F'
PORT_NUMBER_48 = '\x30'
PORT_NUMBER_49 = '\x31'
PORT_NUMBER_50 = '\x32'
PORT_NUMBER_51 = '\x33'
PORT_NUMBER_52 = '\x34'
PORT_NUMBER_53 = '\x35'
PORT_NUMBER_54 = '\x36'
PORT_NUMBER_55 = '\x37'
PORT_NUMBER_56 = '\x38'
PORT_NUMBER_57 = '\x39'
PORT_NUMBER_58 = '\x3A'
PORT_NUMBER_59 = '\x3B'
PORT_NUMBER_60 = '\x3C'
PORT_NUMBER_61 = '\x3D'
PORT_NUMBER_62 = '\x3E'
PORT_NUMBER_63 = '\x3F'
PORT_NUMBER_64 = '\x40'
PORT_NUMBER_65 = '\x41'
PORT_NUMBER_66 = '\x42'
PORT_NUMBER_67 = '\x43'
PORT_NUMBER_68 = '\x44'
PORT_NUMBER_69 = '\x45'
PORT_NUMBER_70 = '\x46'
PORT_NUMBER_71 = '\x47'
PORT_NUMBER_72 = '\x48'
PORT_NUMBER_73 = '\x49'
PORT_NUMBER_74 = '\x4A'
PORT_NUMBER_75 = '\x4B'
PORT_NUMBER_76 = '\x4C'
PORT_NUMBER_77 = '\x4D'
PORT_NUMBER_78 = '\x4E'
PORT_NUMBER_79 = '\x4F'
PORT_NUMBER_80 = '\x50'
PORT_NUMBER_81 = '\x51'
PORT_NUMBER_82 = '\x52'
PORT_NUMBER_83 = '\x53'
PORT_NUMBER_84 = '\x54'
PORT_NUMBER_85 = '\x55'
PORT_NUMBER_86 = '\x56'
PORT_NUMBER_87 = '\x57'
PORT_NUMBER_88 = '\x58'
PORT_NUMBER_89 = '\x59'
PORT_NUMBER_90 = '\x5A'
PORT_NUMBER_91 = '\x5B'
PORT_NUMBER_92 = '\x5C'
PORT_NUMBER_93 = '\x5D'
PORT_NUMBER_94 = '\x5E'
PORT_NUMBER_95 = '\x5F'

PORT_NUMBER_00_07 = '\x60'
PORT_NUMBER_08_15 = '\x61'
PORT_NUMBER_16_23 = '\x62'
PORT_NUMBER_24_31 = '\x63'
PORT_NUMBER_32_39 = '\x64'
PORT_NUMBER_40_47 = '\x65'
PORT_NUMBER_48_55 = '\x66'
PORT_NUMBER_56_63 = '\x67'
PORT_NUMBER_64_71 = '\x68'
PORT_NUMBER_72_79 = '\x69'
PORT_NUMBER_80_87 = '\x6A'
PORT_NUMBER_88_95 = '\x6B'

PORT_NUMBER_00_15 = '\x6C'
PORT_NUMBER_16_31 = '\x6D'
PORT_NUMBER_32_47 = '\x6E'
PORT_NUMBER_48_63 = '\x6F'
PORT_NUMBER_64_79 = '\x70'
PORT_NUMBER_80_95 = '\x71'

PORT_NUMBER_00_31 = '\x72'
PORT_NUMBER_32_63 = '\x73'
PORT_NUMBER_64_95 = '\x74'

PORT_NUMBER_00_95 = '\x75'

PORT_NUMBERS = []
for x in range(96):
    PORT_NUMBERS.append(
        getattr(sys.modules[__name__], f'PORT_NUMBER_{str(x).zfill(2)}')
    )
PORT_NUMBERS.append(PORT_NUMBER_00_07)
PORT_NUMBERS.append(PORT_NUMBER_08_15)
PORT_NUMBERS.append(PORT_NUMBER_16_23)
PORT_NUMBERS.append(PORT_NUMBER_24_31)
PORT_NUMBERS.append(PORT_NUMBER_32_39)
PORT_NUMBERS.append(PORT_NUMBER_40_47)
PORT_NUMBERS.append(PORT_NUMBER_48_55)
PORT_NUMBERS.append(PORT_NUMBER_56_63)
PORT_NUMBERS.append(PORT_NUMBER_64_71)
PORT_NUMBERS.append(PORT_NUMBER_72_79)
PORT_NUMBERS.append(PORT_NUMBER_80_87)
PORT_NUMBERS.append(PORT_NUMBER_88_95)

PORT_NUMBERS.append(PORT_NUMBER_00_15)
PORT_NUMBERS.append(PORT_NUMBER_16_31)
PORT_NUMBERS.append(PORT_NUMBER_32_47)
PORT_NUMBERS.append(PORT_NUMBER_48_63)
PORT_NUMBERS.append(PORT_NUMBER_64_79)
PORT_NUMBERS.append(PORT_NUMBER_80_95)

PORT_NUMBERS.append(PORT_NUMBER_00_31)
PORT_NUMBERS.append(PORT_NUMBER_32_63)
PORT_NUMBERS.append(PORT_NUMBER_64_95)

PORT_NUMBERS.append(PORT_NUMBER_00_95)
