package com.qmai.zqtoolkit.base

import android.content.Context
import android.util.Log
import com.blankj.utilcode.util.TimeUtils
import com.qmai.zqtoolkit.ConnectState
import com.qmai.zqtoolkit.LivingWeight
import com.qmai.zqtoolkit.ScaleInfo
import com.qmai.zqtoolkit.base.scale.ScaleBaseKit
import com.qmai.zqtoolkit.config.QmScaleBrand
import com.zqebsdk.zqebsdk
import com.zqprintersdk.PrinterConst
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn

/**
 *  author : tongzi
 *  date : 2022/2/10 14:18
 *  description :中崎电子秤
 */
object ZqScaleKit : ScaleBaseKit() {
    override val TAG: String
        get() = "ZqScaleKit"
    override val STABLE_COUNT: Int
        get() = 13
    override val CONECT_CHECK_COUNT: Int
        get() = 4
    override val SCALE_TYPE: QmScaleBrand
        get() = QmScaleBrand.ZQEB


    override fun connect(cxt: Context?, scale: ScaleInfo) {
        super.connect(cxt, scale)
        val ebConnect =
            zqeb.EB_Connect(
                String.format("%s:%s", scale.port ?: "ttyS4", scale.buad ?: "9600"),
                cxt
            )
        updateScaleInfo("${TAG} :connect " + TimeUtils.getNowString())
        when (ebConnect) {
            PrinterConst.ErrorCode.SUCCESS -> {
                GlobalScope.launch {
                    flow {
                        connectCache.clear()
                        for (i in 0..CONECT_CHECK_COUNT) {
                            emit(getWeightTare().isStable)
                            delay(80)
                        }
                    }.collect {
                        when {
                            connectCache.size >= CONECT_CHECK_COUNT -> {
                                if (connectCache.any { cn -> cn })
                                    updateState(ConnectState(true, "打开成功"))
                                else updateState(ConnectState(false, "打开失败"))
                                connectCache.clear()
                            }
                            else -> connectCache.add(it)
                        }
                    }
                }
            }
            else -> updateState(
                ConnectState(
                    ebConnect == PrinterConst.ErrorCode.SUCCESS, when (ebConnect) {
                        PrinterConst.ErrorCode.INVALIDPARAM -> "打印机参数无效"
                        PrinterConst.ErrorCode.PORTERROR -> "端口错误"
                        PrinterConst.ErrorCode.NOPERMISSION -> "没有该端口的访问权限"
                        else -> "未知错误"
                    }
                )
            )
        }

    }

    private val zqeb by lazy {
        zqebsdk()
    }
    private var job: Job? = null

    override fun disconnect() {
        super.disconnect()
        val ebDisconnect = zqeb.EB_Disconnect()
        Log.v(TAG, String.format("ebDisconnect: %s", ebDisconnect))
    }

    //置零
    override fun setZero() {
        if (isScaleSuccess()) {
            val ebSetzero = zqeb.EB_SetZero()
            Log.v(TAG, String.format("ebSetzero: %s", ebSetzero))
        }
    }

    //去皮
    override fun setNetWeight() {
        if (isScaleSuccess()) {
            val ebSetnetweight = zqeb.EB_SetNetWeight()
            Log.v(TAG, String.format("ebSetnetweight: %s", ebSetnetweight))
        }
    }

    //数字去皮
    override fun setNetWeightByElec(tare: Double) {
        if (isScaleSuccess()) {
            val sbSetTare = zqeb.EB_SetTare(tare)
            Log.v(TAG, String.format("sbSetTare: %s", sbSetTare))
        }
    }

    //清皮
    override fun clearTare() {
        if (isScaleSuccess()) {
            val ebCleartare = zqeb.EB_ClearTare()
            Log.v(TAG, String.format("ebCleartare: %s", ebCleartare))
        }
    }


    //读取电子秤参数
    override fun getParameter(): Array<String> {
        var parameter: Array<String> = arrayOf()
        if (isScaleSuccess()) {
            parameter = zqeb.EB_GetParameter()
            Log.v(TAG, String.format("parameter: %s", parameter))
        }
        return parameter
    }

    private val weightFlow = flow {
        while (true) {
            emit(Unit)
            delay(80)
        }
    }

    override fun stopReadData() {
        job?.cancel()
        job = null
    }

    override fun readData() {
        if (job != null && job?.isActive == true) {
            return
        }
        job = GlobalScope.launch {
            if (isActive) {
                weightFlow.flowOn(Dispatchers.IO)
                    .collect {
                        updateWeight(getWeightTare())
                    }
            }
        }
    }

    //读取重量、皮重
    private fun getWeightTare(): LivingWeight {
        val strRet: Array<String> = zqeb.EB_GetWeightTare()
        Log.v(
            TAG, String.format(
                "%s,%s,%s",
                strRet[0], strRet[1], strRet[2]
            )
        )
        var strState = ""
        var strWeight = ""
        var strTare = ""
        var strUnit = ""
        if (!strRet[1].isNullOrEmpty()) {
            strUnit = strRet[1].replace("[^a-z^A-Z]".toRegex(), "")
            strWeight = strRet[1].replace(strUnit, "")
        }
        if (!strRet[2].isNullOrEmpty()) {
            var strUnitTare = strRet[2].replace("[^a-z^A-Z]".toRegex(), "")
            strTare = strRet[2].replace(strUnitTare, "")
        }

        //0是读取成功  2且读数<0也是稳定
        if (Integer.valueOf(strRet[0]) == 0 || (Integer.valueOf(strRet[0]) == 2
                    && strWeight.isNotEmpty() && strWeight.toFloat() < 0)
        ) {
            strState = "OK"
            return LivingWeight(
                true,
                strWeight.trim(),
                strUnit,
                strTare.trim(),
                false
            )
        } else {
//            when (Integer.valueOf(strRet[0])) {
//                -3 -> strState = "Data wrong"
//                -2 -> strState = "Read Data Error"
//                -1 -> strState = "Port Error"
//                1 -> strState = "Weight instability"
//                2 -> strState = "Weight overflow or not ZERO"
//            }
            return LivingWeight(
                false,
                strWeight.trim(),
                strUnit, strTare.trim(),
                Integer.valueOf(strRet[0]) == -2 || Integer.valueOf(strRet[0]) == -3
            )
        }
    }

}

