package com.module.pay.strategy

import android.util.Log
import com.module.pay.serialport.DataUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils
import com.quyunshuo.androidbaseframemvvm.common.constant.Heartbeat
import com.quyunshuo.androidbaseframemvvm.common.constant.MMKVName
import com.quyunshuo.androidbaseframemvvm.common.constant.PayName
import com.quyunshuo.androidbaseframemvvm.common.constant.event.ApiMessageEvent
import com.quyunshuo.androidbaseframemvvm.common.util.ByteUtils
import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import java.io.OutputStream
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.Locale

/**
 * ict rs232 接受和发送数据 策略实现类
 */
class SerialPortMDBStrategy : SerialPortStrategy {
    private val TAG = "SerialPortMDBStrategy"

    //纸币器支持的币值
    private val moneyList: ArrayList<String> = ArrayList()

    //防止数据阶段的情况，需要存储起来。
    var sber: StringBuilder = StringBuilder()
    private var dmultiplyingPower: Double? = null
    private var createStrategy: PaySendDataStrategy? = null
    //是否初始化成功 false表示没有 true表示有
    var setupSuccessBill = false
    //刷卡器失去通讯次数
    var creditCardFFCount = 0

    init {
        createStrategy = PaySendDataFactory.createStrategy(StrategyType.MDB)
    }


    override fun readData(data: ByteArray, i: Int, size: Int) {
        val ascii = String(data, charset("ascii"))

        if (ascii.contains("\n")) {
            val substring = ascii.substring(0, size)
            sber.append(substring)
            val split: Array<String> =
                sber.toString().split("\n".toRegex()).dropLastWhile { it.isEmpty() }
                    .toTypedArray()

            for (s1 in split) {
                XLogUtil.d("s1:"+s1)
                if ("30 03" == s1) {
                    continue
                }
                disposeData(s1.trim())
            }
            sber.delete(0, sber.length)
        } else {
            val substring = ascii.substring(0, size)
            sber.append(substring)
            XLogUtil.d("sber:"+sber.toString())
        }
    }

    override fun sendData(data: String, outputStream: OutputStream?) {
        XLogUtil.d("MDB sendData: $data")
        try {
            if (outputStream != null) {
                val sendData: ByteArray = DataUtils.HexToByteArr(data)
                outputStream.write(sendData)
                outputStream.flush()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun disposeData(asciiData: String) {
        XLogUtil.d("MDB Read Data: $asciiData")
        //处理纸币数据
        billData(asciiData)
        //处理刷卡器数据
        creditCard(asciiData)

    }

    private fun creditCard(asciiData: String) {
        if (asciiData.startsWith("10 01") || asciiData.startsWith("01 03") || asciiData.startsWith("01 02")) { //初始化
            val s = asciiData.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
//            cardSetupSuccess = true
//            if (s.size >= 5) {
//                if (Hawk.get(Name.KOREA, false) || Hawk.get(Name.VENDIM, false)) {
//                    Global.creditCardMultiplier = decimalPoint1(s[5].toInt())
//                }
//            }
        } else if (asciiData.startsWith("10 0B")) {//刷卡器异常
            CoroutineScope(Dispatchers.IO).launch {
                createStrategy?.initCreditCard()//重新的初始化

            }
            //EventBus.getDefault().post(OfflineMessageEvent(Name.SESSION_ERROR, null))

        }else if (asciiData.startsWith("10 00")) {//刷卡器准备就绪
//            CoroutineScope(Dispatchers.IO).launch {
//                createStrategy?.initCreditCard()//重新的初始化
//
//            }
        } else if ("00" == asciiData) {//说明数据发送成功
            if (creditCardFFCount>=3){
                creditCardFFCount=0
                CoroutineScope(Dispatchers.IO).launch {
                    createStrategy?.initCreditCard()//重新的初始化
                }
            }
            creditCardFFCount=0

        }else if ("FF"== asciiData) {//说明数据发送失败，刷卡器用于需要重新初始化 这里有一个问题，其他的指令也会出现ff。，其他指令也有00，唉。麻烦。使用一条一条发是行不通的。
            if (creditCardFFCount<3){
                creditCardFFCount++

            }

        } else if (asciiData.startsWith("10 07") || asciiData.startsWith("07")) {//End Session
            EventBus.getDefault().post(ApiMessageEvent(PayName.MDB_CARD_ENDSESSION,""))
        } else if (asciiData.startsWith("10 06") || asciiData.startsWith("06")) {//Vend Denied
            createStrategy?.creditCardSessionComplete()
            EventBus.getDefault().post(ApiMessageEvent(PayName.MDB_CARD_DENIED,""))
        } else if (asciiData.startsWith("10 04") || asciiData.startsWith("04")) {//Session Cancel  Request
            EventBus.getDefault().post(ApiMessageEvent(PayName.MDB_CARD_CANCEL,""))
        } else if (asciiData.startsWith("10 05") || asciiData.startsWith("05") || (asciiData.length >= 5 && asciiData.substring(
                2,
                4
            ) == "05")
        ) {//Vend Approved
            EventBus.getDefault().post(ApiMessageEvent(PayName.MDB_CARD_SUCCESS,""))
        }else if (asciiData.startsWith("10 03") || asciiData.startsWith("03")) {//Begin Session
            EventBus.getDefault().post(ApiMessageEvent(PayName.MDB_CARD_BEGINSESSION,""))

        }
    }

    private fun billData(asciiData: String) {
        if (asciiData.startsWith("01 ") or asciiData.startsWith("02 ")) {
            //这个是setup返回的信息，这里发送使能
            val s = asciiData.split(" ")
            //我们需要记录下倍率。
            if (s.size >= 12) {
                moneyList.clear()
                val mp: String = ByteUtils.hexStr2decimal(s[3] + s[4]).toString()
                dmultiplyingPower = mp.toDouble() / decimalPoint(s[5].toInt())
                var number = 0
                for (i in 11 until s.size - 1) {
                    if ("00" == s[i]) {
                        if (number >= 1) {
                            break
                        }
                        if (i > s.size - 3) {
                            break
                        }
                        number++
                    }
                    moneyList.add(s[i].toInt(16).toString() + "")
                }
                val s2: String = moneyList[moneyList.size - 1]
                if ("0" == s2) {
                    moneyList.removeAt(moneyList.size - 1) //如果等于00，则移除最后一个元素
                }
                val s1: String =
                    str2HexString(moneyList, moneyList.size).uppercase(Locale.getDefault())
                XLogUtil.d("-s1:$s1")
                if (SpUtils.getBoolean(MMKVName.BILL_COLLOCATION, false)!!) {
                    //托管
                    createStrategy?.billEnable(s1, s1)

                } else {
                    //不托管
                    createStrategy?.billEnable(s1, "0000")
                }
                setupSuccessBill = true

            }
        } else if (asciiData.startsWith("30 09")) { //还没有使能
            //发送setup，如果获取到信息就停止。
            //如果没有休眠就要初始化，如果已经初始化成功就不要发了。
            Log.d(
                TAG,
                "billData 30 09: " + SpUtils.getBoolean(
                    MMKVName.SLEEP,
                    false
                )!! + ":" + setupSuccessBill
            )
            if (!SpUtils.getBoolean(MMKVName.SLEEP, false)!! && !setupSuccessBill) {
                createStrategy?.billInit()
            }
        } else if (asciiData.startsWith("30 80")) { //第一票据
            billCalculationAmount(0)
        } else if (asciiData.startsWith("30 81")) { //第二票据
            billCalculationAmount(1)
        } else if (asciiData.startsWith("30 82")) {
            billCalculationAmount(2)
        } else if (asciiData.startsWith("30 83")) {
            billCalculationAmount(3)
        } else if (asciiData.startsWith("30 84")) {
            billCalculationAmount(4)
        } else if (asciiData.startsWith("30 85")) {
            billCalculationAmount(5)
        } else if (asciiData.startsWith("30 86")) {
            billCalculationAmount(6)
        } else if (asciiData.startsWith("30 87")) {
            billCalculationAmount(7)
        } else if (asciiData.startsWith("30 88")) {
            billCalculationAmount(8)
        } else if (asciiData.startsWith("30 89")) {
            billCalculationAmount(9)
        } else if (asciiData.startsWith("30 90") or asciiData.startsWith("30 91") or asciiData.startsWith(
                "30 92"
            ) or asciiData.startsWith("30 93") or
            asciiData.startsWith("30 94") or asciiData.startsWith("30 95") or asciiData.startsWith("30 96") or asciiData.startsWith(
                "30 97"
            ) or
            asciiData.startsWith("30 98")
        ) {
            createStrategy?.squeezeMoney()
        } else if (asciiData.startsWith("30 06")) { //表示复位中
            createStrategy?.billInit()
        } else if (asciiData.startsWith("MDB-RS232")) {
            setupSuccessBill = false //mdb板重启了。
        } else if (asciiData.startsWith("30 01") or asciiData.startsWith("30 02") /*| asciiData.startsWith("30 03")*/ or asciiData.startsWith(
                "30 04"
            ) or
            asciiData.startsWith("30 05") or asciiData.startsWith("30 08") or asciiData.startsWith("30 0A") /*|asciiData.startsWith("30 0B")*/) {
            //错误信息收集
        }

    }

    //自动压钞，我们只需要累加钱就可以了。
    private fun billCalculationAmount(i2: Int) {
        XLogUtil.d("moneyList.size:" + moneyList.size)
        if (moneyList.size >= i2) {
            val sum1 = BigDecimal(moneyList[i2].toInt().toString() + "")
            val sum2 = BigDecimal(dmultiplyingPower.toString() + "")
            Heartbeat.acceptBill =
                Heartbeat.acceptBill.add(sum1.multiply(sum2)).setScale(2, RoundingMode.HALF_UP)
            EventBus.getDefault().post(ApiMessageEvent(PayName.ACCEPT_BILL, Heartbeat.acceptBill))
        }
    }

    //计算出纸币器可以接受的钱。也就是挡位，比如135，那么就需要计算。
    private fun str2HexString(moneyList: List<String>, number: Int): String {
        val sb = java.lang.StringBuilder()
        for (i1 in 0 until number) {
            if ("00" == moneyList[i1]) {
                sb.append(0)
            } else {
                sb.append(1)
            }
        }
        var s = Integer.toHexString(sb.toString().toInt(2))
        val length = s.length
        for (i in 0 until 4 - length) {
            s = "0$s"
        }
        return s
    }

    //倍率计算
    fun decimalPoint(number: Int): Int {
        var asdf = 1
        for (i in 0 until number) {
            asdf *= 10
        }
        return asdf
    }

    //倍率计算 刷卡器
    fun decimalPoint1(number: Int): Int {
        if (number == 1) {
            return 1
        }
        var asdf = 1
        for (i in 0 until number) {
            asdf *= 10
        }
        return asdf
    }
}