package com.grkj.iscs.modbus

import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_CARD
import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_FINGERPRINT
import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_KEY
import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_LOCK
import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_ELEC_LOCK_BOARD
import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_KEY
import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_LOCK
import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_PORTABLE
import com.grkj.iscs.util.log.LogUtil

/**
 * RS-485 设备底座 Bean
 *
 * @param addr 设备地址 0x01-0x16
 * @param type 0x00：钥匙底座 0x01：锁具底座  0x02：电磁锁控制板 0x03：便携式底座
 * @param deviceList 设备列表
 */
class DockBean(
    var addr: Byte,
    var type: Byte?,
    var deviceList: MutableList<DeviceBean>
) {

    fun parseStatus(byteArray: ByteArray): DockBean? {
        if (byteArray.isEmpty()) {
            return null
        }
        type?.let {
            // 因为都是一个寄存器返回的，所以一定能得到2个钥匙的状态或者10把锁具的状态
            when (it) {
                DOCK_TYPE_KEY -> {
                    val leftHasKey = (byteArray[4].toInt() shr 0) and 0x1 == 1
                    val isLeftCharging = (byteArray[4].toInt() shr 1) and 0x1 == 1
                    val rightHasKey = (byteArray[3].toInt() shr 0) and 0x1 == 1
                    val isRightCharging = (byteArray[3].toInt() shr 1) and 0x1 == 1
                    LogUtil.i("钥匙刷新状态 ： $leftHasKey - $isLeftCharging - $rightHasKey - $isRightCharging")
                    if (getKeyList().isEmpty()) {
                        deviceList.add(KeyBean(0, leftHasKey, true, isLeftCharging, null, null))
                        deviceList.add(KeyBean(1, rightHasKey, false, isRightCharging, null, null))
                        return null
                    }

                    val changeList = mutableListOf<DeviceBean>()
                    getKeyList().forEach { keyBean ->
                        if (keyBean.isLeft) {
                            if (leftHasKey != keyBean.isExist) {
                                keyBean.isExist = leftHasKey
                                keyBean.isCharging = isLeftCharging

                                // 拿走钥匙，移除钥匙信息
                                if (!leftHasKey) {
                                    changeList.add(keyBean.clone())
                                    keyBean.rfid = null
                                    keyBean.mac = null
                                } else {
                                    changeList.add(keyBean)
                                }
                            }
                        } else {
                            if (rightHasKey != keyBean.isExist) {
                                keyBean.isExist = rightHasKey
                                keyBean.isCharging = isRightCharging
                                // 拿走钥匙，移除钥匙信息
                                if (!rightHasKey) {
                                    changeList.add(keyBean.clone())
                                    keyBean.rfid = null
                                    keyBean.mac = null
                                } else {
                                    changeList.add(keyBean)
                                }
                            }
                        }
                    }

                    return DockBean(addr, it, changeList)
                }
                DOCK_TYPE_LOCK -> {
                    val tempList = mutableListOf<Boolean>()
                    for (i in 0..7) {
                        tempList.add((byteArray[4].toInt() shr i) and 0x1 == 1)
                    }
                    tempList.add((byteArray[3].toInt() shr 0) and 0x1 == 1)
                    tempList.add((byteArray[3].toInt() shr 1) and 0x1 == 1)

                    if (getLockList().isEmpty()) {
                        for (i in 0 until tempList.size) {
                            deviceList.add(LockBean(i, tempList[i], null))
                        }
                    }

                    val changeList = mutableListOf<DeviceBean>()
                    for (i in 0 until getLockList().size) {
                        if (getLockList()[i].isExist != tempList[i]) {
                            getLockList()[i].isExist = tempList[i]
                            // 拿走锁具，移除锁具信息
                            if (!tempList[i]) {
                                changeList.add(getLockList()[i].clone())
                                getLockList()[i].rfid = null
                            } else {
                                changeList.add(getLockList()[i])
                            }
                        }
                    }

                    LogUtil.i("锁具刷新状态 ： $changeList")
                    return DockBean(addr, it, changeList)
                }
                DOCK_TYPE_ELEC_LOCK_BOARD -> {
                    // TODO 临时占位
                    return null
                }
                DOCK_TYPE_PORTABLE -> {
                    // TODO 便携式底座更新
                    val tempList = mutableListOf<Boolean>()
                    for (i in 0..2) {
                        tempList.add((byteArray[4].toInt() shr i) and 0x1 == 1)
                    }
                    if (getLockList().isEmpty()) {
                        for (i in 0 until tempList.size) {
                            deviceList.add(LockBean(i, tempList[i], null))
                        }
                    }

                    val isKeyExist = (byteArray[3].toInt() shr 0) and 0x1 == 1
                    val isKeyCharging = (byteArray[3].toInt() shr 1) and 0x1 == 1

                    if (getKeyList().isEmpty()) {
                        deviceList.add(KeyBean(4, isKeyExist, true, isKeyCharging, null, null))
                    }

                    val isCardExist = (byteArray[3].toInt() shr 4) and 0x1 == 1
                    val isFingerPrintExist = (byteArray[3].toInt() shr 5) and 0x1 == 1
                    val isDockCharging = (byteArray[3].toInt() shr 6) and 0x1 == 1
                    val isDockFullCharged = (byteArray[3].toInt() shr 7) and 0x1 == 1
                    LogUtil.i("便携式底座状态 ： $isCardExist - $isFingerPrintExist - $isDockCharging - $isDockFullCharged")

                    // TODO 便携柜 list
                    if (getCardList().isEmpty()) {
                        deviceList.add(CardBean(0, isCardExist))
                    }

                    if (getFingerPrintList().isEmpty()) {
                        deviceList.add(FingerPrintBean(0, isFingerPrintExist))
                    }

                    val changeList = mutableListOf<DeviceBean>()
                    // 锁具变化
                    for (i in 0 until getLockList().size) {
                        if (getLockList()[i].isExist != tempList[i]) {
                            getLockList()[i].isExist = tempList[i]
                            changeList.add(getLockList()[i].clone())
                            // 拿走锁具，移除锁具信息
                            if (!tempList[i]) {
                                getLockList()[i].rfid = null
                            }
                        }
                    }
                    // 蓝牙钥匙变化
                    if (getKeyList()[0].isExist != isKeyExist) {
                        getKeyList()[0].isExist = isKeyExist
                        changeList.add(getKeyList()[0].clone())
                        // 拿走钥匙，移除钥匙信息
                        if (!isKeyExist) {
                            getKeyList()[0].rfid = null
                            getKeyList()[0].mac = null
                        }
                    }
                    // 卡片变化
                    if (getCardList()[0].isExist != isCardExist) {
                        getCardList()[0].isExist = isCardExist
                        changeList.add(getCardList()[0])
                    }
                    // 指纹变化
                    if (getFingerPrintList()[0].isExist != isFingerPrintExist) {
                        getFingerPrintList()[0].isExist = isFingerPrintExist
                        changeList.add(getFingerPrintList()[0])
                    }
                    LogUtil.i("便携式刷新状态 ： $changeList")
                    return DockBean(addr, it, changeList)
                }
                else -> return null
            }
        } ?: return null
    }

    fun getKeyList(): MutableList<KeyBean> {
        return deviceList.filter { it.type == DEVICE_TYPE_KEY } as MutableList<KeyBean>
    }

    fun getLockList() : MutableList<LockBean> {
        return deviceList.filter { it.type == DEVICE_TYPE_LOCK } as MutableList<LockBean>
    }

    fun getCardList(): MutableList<CardBean> {
        return deviceList.filter { it.type == DEVICE_TYPE_CARD } as MutableList<CardBean>
    }

    fun getFingerPrintList(): MutableList<FingerPrintBean> {
        return deviceList.filter { it.type == DEVICE_TYPE_FINGERPRINT } as MutableList<FingerPrintBean>
    }

    fun getBit(by: Byte): String {
        val sb = StringBuffer()
        sb.append((by.toInt() shr 7) and 0x1)
            .append((by.toInt() shr 6) and 0x1)
            .append((by.toInt() shr 5) and 0x1)
            .append((by.toInt() shr 4) and 0x1)
            .append((by.toInt() shr 3) and 0x1)
            .append((by.toInt() shr 2) and 0x1)
            .append((by.toInt() shr 1) and 0x1)
            .append((by.toInt() shr 0) and 0x1)
        return sb.toString()
    }

    override fun toString(): String {
        return "DockBean(addr=$addr, type=$type, deviceList=$deviceList)"
    }


    /**
     * 通用设备信息Bean
     *
     * @param type 0：钥匙 1：锁
     * @param idx 锁具底座时：锁具序号 0-9  钥匙底座时：0-左 1-右    便携式底座：锁具0-2 钥匙0
     * @param isExist true：有设备 false：无设备
     */
    sealed class DeviceBean(
        var type: Int,
        var idx: Int,
        var isExist: Boolean
    ) {
        override fun toString(): String {
            return "DeviceBean(type=$type, idx=$idx, isExist=$isExist)"
        }
    }

    /**
     * 钥匙
     */
    // TODO isLeft待移除，使用idx替代
    class KeyBean(
        idx: Int,
        isExist: Boolean,
        var isLeft: Boolean,
        var isCharging: Boolean,
        var rfid: String?,
        var mac: String?
    ) : DeviceBean(DEVICE_TYPE_KEY, idx, isExist) {
        override fun toString(): String {
            return "KeyBean(isLeft=$isLeft, isCharging=$isCharging, rfid=$rfid, mac=$mac)"
        }

        fun clone(): KeyBean {
            return KeyBean(idx, isExist, isLeft, isCharging, rfid, mac)
        }
    }

    /**
     * 锁具
     *
     * @param rfid 锁具的RFID(仅有关闭锁扣的时候读取并保存，否则为null)
     */
    class LockBean(
        idx: Int,
        isExist: Boolean,
        var rfid: String?
    ) : DeviceBean(DEVICE_TYPE_LOCK, idx, isExist) {
        override fun toString(): String {
            return "LockBean(rfid=$rfid)"
        }

        fun clone(): LockBean {
            return LockBean(idx, isExist, rfid)
        }
    }

    /**
     * 卡
     */
    class CardBean(
        idx: Int,
        isExist: Boolean
    ) : DeviceBean(DEVICE_TYPE_CARD, idx, isExist)

    /**
     * 指纹
     */
    class FingerPrintBean(
        idx: Int,
        isExist: Boolean
    ) : DeviceBean(DEVICE_TYPE_FINGERPRINT, idx, isExist)
}
