from enum import Enum
import struct
import time

class ParmEnum(Enum):
    readonly = 0
    writeable = 1


class Parm():
    name = None
    value = '读取错误'
    slot = None
    relativeIndex = None
    realIndex = None
    dataType = None
    size = None
    desc = None
    rdType = None
    def __init__(self, parmData:list, slot:int, startIndex:int, block):
        # print(startIndex, self.relativeIndex)
        # print(parmData)
        self.relativeIndex, self.paramName, self.desc, self.dataType, rdStr, self.size, *rest = parmData
        self.relativeIndex = int(self.relativeIndex)
        self.rdType = ParmEnum.readonly if rdStr == 'r' else ParmEnum.writeable
        self.realIndex = startIndex + self.relativeIndex
        self.slot = slot
        self.DPV1Master = block.DPV1Master
        self.address = block.address
        # print(self.relativeIndex, self.paramName, self.desc, self.dataType, self.rdType, self.size)

    def readValue(self):
        value = self.DPV1Master.readParm(address = self.address, slot = self.slot, index = self.realIndex, length = self.size)
        if value == '读取错误':
            return '读取错误'
        else:
            return self.unpackValue(value)

    def writeParm(self, values):
        valueByte = self.packValue(*values)
        result = self.DPV1Master.writeParm(address = self.address, slot = self.slot, index = self.realIndex, length = self.size, valueByte = valueByte)
    
    def unpackValue(self, value):
        match self.dataType:
            case 'Unsigned8':
                return self.unpackU8(value)
            case 'Unsigned16':
                return self.unpackU16(value)
            case 'Unsigned32':
                return self.unpackU32(value)
            case 'Float':
                return self.unpackFloat(value)
            case '101':
                return self.unpack101(value)
            case 'DS-32':
                return self.unpackDS32(value)
            case 'DS-36':
                return self.unpackDS36(value)
            case 'DS-37':
                return self.unpackDS37(value)
            case 'DS-39':
                return self.unpackDS39(value)
            case 'DS-50':
                return self.unpackDS50(value)
            case 'OctetString' | 'VisibleString':
                return self.unpackStr(value)
            case 'FloatList2':
                return self.unpackFloatList2(value)
            case _:
                return str(value)

    def packValue(self, values):
        match self.dataType:
            case 'Unsigned8':
                return self.packU8(values)
            case 'Unsigned16':
                return self.packU16(values)
            case 'Unsigned32':
                return self.packU32(values)
            case 'Float':
                return self.packFloat(values)
            case '101':
                return self.pack101(values)
            case 'DS-32':
                return self.packDS32(values)
            case 'DS-36':
                return self.packDS36(values)
            case 'DS-50':
                return self.packDS50(values)
            case 'OctetString' | 'VisibleString':
                return self.packStr(values)
            case 'FloatList2':
                return self.packFloatList2(values)
            case _:
                return 

    def unpackU8(self, value):
        return str(struct.unpack('>b', value)[0])

    def unpackU16(self, value):
        return str(struct.unpack('>h', value)[0])

    def unpackU32(self, value):
        return str(struct.unpack('>i', value)[0])

    def unpackFloat(self, value):
        return str(round(struct.unpack('>f', value)[0], 4))

    def unpackStr(self, value):
        return struct.unpack('{}s'.format(str(len(value))), value)[0]

    def unpack101(self, value):
        valueByte, statusByte = value[:4], value[4].to_bytes(1, byteorder='little')
        value = self.unpackFloat(valueByte)
        status = self.unpackU8(statusByte)
        displayStr = '值:{} 状态:{}'.format(value, status)
        return displayStr

    def unpackDS32(self, value):
        reserved = self.unpackU8(value[0:1])
        blockObject = self.unpackU8(value[1:2])
        parentClass = self.unpackU8(value[2:3])
        clas = self.unpackU8(value[3:4])
        devRev = self.unpackU16(value[4:6])
        devRevComp = self.unpackU16(value[6:8])
        ddRevision = self.unpackStr(value[8:10])
        profile = self.unpackStr(value[10:12])
        profileRevision = self.unpackU16(value[12:14])
        executionTime = self.unpackU8(value[14:15])
        numberOfParameters = self.unpackU16(value[15:17])
        addressOfView1 = self.unpackU16(value[17:19])
        numberOfViews = self.unpackU8(value[19:20])
        return ''


    def unpackDS36(self, value):
        EU100Byte, EU0Byte, unitByte, decPointByte = value[:4], value[4:], value[8:10], value[10].to_bytes(1, byteorder='little')
        EU100 = self.unpackFloat(EU100Byte)
        EU0 = self.unpackFloat(EU0Byte)
        decPoint = self.unpackU8(decPointByte)
        unitValue = self.unpackU16(unitByte)
        unit = self.unitConver(unitValue)
        displayStr = '有效上限:{}\r\n有效下限:{}\r\n单位:{}\r\n小数点:{}'.format(EU100, EU0, unit, decPoint)
        return displayStr

    def unpackDS37(self, value):
        actualByte, permitByte, normalByte = value[0].to_bytes(1, byteorder='little'), value[1].to_bytes(1, byteorder='little'), value[2].to_bytes(1, byteorder='little')
        # print(type(actualByte), permitByte, normalByte)
        actualMode = self.unpackU8(actualByte)
        permitMode = self.unpackU8(permitByte)
        normalMode = self.unpackU8(normalByte)
        displayStr = '实际模式:{}\r\n允许模式:{}\r\n正常模式:{}'.format(actualMode, permitMode, normalMode)
        return displayStr

    def unpackDS39(self, value):
        unacknowledgByte, alarmStateByte, timeStampByte, subcodeByte, alarmValueByte = value[0].to_bytes(1, byteorder='little'), value[1].to_bytes(1, byteorder='little'), value[2:10], value[10:12], value[12:16]
        unacknowledg = self.unpackU8(unacknowledgByte)
        alarmState = self.unpackU8(alarmStateByte)
        subcode = self.unpackU16(subcodeByte)
        alarmValue = self.unpackFloat(alarmValueByte)
        timestamp = int.from_bytes(timeStampByte, byteorder='big')
        timeStr = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp))
        displayStr = 'Unacknowledged:{}\r\n有无报警{}\r\n时间戳:{}\r\n报警原因:{}\r\n引起报警的值:{}'.format(unacknowledg, alarmState, timeStr, subcode, alarmValue)
        return displayStr

    def unpackDS50(self, value):
        simulateStatusByte, simulateValueByte, simulateEnabledByte = value[0].to_bytes(1, byteorder='little'), value[1:5], value[5].to_bytes(1, byteorder='little')
        simulateStatus = self.unpackU8(simulateStatusByte)
        simulateValue = self.unpackFloat(simulateValueByte)
        simulateEnabled = self.unpackU8(simulateEnabledByte)
        displayStr = '仿真值状态:{}\r\n仿真值:{}\r\n是否启用仿真:{}'
        return displayStr

    def unpackFloatList2(self, value):
        float1Byte, float2Byte = value[:4], value[4:8]
        float1 = self.unpackFloat(float1Byte)
        float2 = self.unpackFloat(float2Byte)
        displayStr = '值1:{}\r\n值2:{}'.format(float1, float2)
        return displayStr


    def packU8(self, value):
        return struct.pack('>b', int(value))

    def packU16(self, value):
        return struct.pack('>h', int(value))

    def packFloat(self, value):
        return struct.pack('>f', float(value))

    def packU32(self, value):
        return struct.pack('>i', int(value))

    def pack101(self, value, status):
        valueByte = self.packFloat(value)
        statusByte = self.packU8(status)
        packedData = valueByte + statusByte
        return packedData

    def packDS36(self, EU100, EU0, unitValue, decPoint):
        EU100Byte = self.packFloat(EU100)
        EU0Byte = self.packFloat(EU0)
        unitByte = self.packU16(unitValue)
        decPointByte = self.packU8(decPoint)
        packedData = EU100Byte + EU0Byte + unitByte + decPointByte
        return packedData


    def packDS50(self, simulateStatus, simulateValue, simulateEnabled):
	    simulateStatusByte = self.packU8(simulateStatus)
	    simulateValueByte = self.packFloat(simulateValue)
	    simulateEnabledByte = self.packU8(simulateEnabled)
	    packedData = simulateStatusByte + simulateValueByte + simulateEnabledByte
	    return packedData

    def packFloatList2(self, float1, float2):
        float1Byte = self.packFloat(float1)
        float2Byte = self.packFloat(float2)
        packedData = float1Byte + float2Byte
        return packedData

    def unitConver(self, unitValue):
        unit, desc = '1', '1'
        return unit + desc
