package cn.muchinfo.rma.business.quote.adapter

import cn.muchinfo.rma.business.quote.models.MoQuotaSubscriptReq
import cn.muchinfo.rma.business.quote.models.MoQuoteSubscriptGoodsInfo
import cn.muchinfo.rma.netcore.packet.Packet40
import cn.muchinfo.rma.protobuf.classNumber.ClassNumber
import java.lang.Exception
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.charset.Charset

/**
 * 行情数据解析类
 */
class QuoteAdapter {
    companion object {
        /**
         * 构建行情订阅请求包
         * @param goodsCodes HashSet<String> 待订阅商品集合
         * @param token String 登录令牌
         * @param loginID Int 账户编号
         * @return Packet40 行情订阅请求包
         */
        fun buildSubscriptPacket(
            goodsCodes: Set<String>,
            token: String,
            loginID: Long
        ): Packet40 {
            // 订阅商品列表
            val quoteSubscriptGoodsIfs: ArrayList<MoQuoteSubscriptGoodsInfo> =
                ArrayList()
            for (goodsCode in goodsCodes) {
                quoteSubscriptGoodsIfs.add(MoQuoteSubscriptGoodsInfo(goodsCode = goodsCode))
            }

            // 订阅请求对象
            val moQuoteSubscriptReq = MoQuotaSubscriptReq(
                accountID = loginID,
                token = token,
                count = quoteSubscriptGoodsIfs.size,
                quoteSubscriptGoodsInfo = quoteSubscriptGoodsIfs
            )

            return Packet40(
                ClassNumber.MainClassNumber_Quota_SubscriptReq.toByte(),
                0,
                moQuoteSubscriptReq.getData()
            )
        }

        /**
         * 解析实时行情订阅回复报文的方法
         * @param packet Packet40 实时行情订阅回复报文
         * @return Triple<Boolean, Error?, List<MoQuoteSubscriptGoodsInfo>?>
         */
        fun analySubscriptRsp(packet: Packet40): Triple<Boolean, Error?, List<MoQuoteSubscriptGoodsInfo>?> {
            if (packet.content.isEmpty()) {
                // 实时行情订阅回复报文错误
                return Triple(false, Error("实时行情订阅回复报文错误"), null)
            }

            // 判断订阅是否成功
            val count = ByteBuffer.wrap(packet.content.sliceArray(0 until 4), 0, 4)
                .order(ByteOrder.BIG_ENDIAN).int
            if (count == -1 || count == -2 || count == -3) {
                // 订阅失败, Token校验失败, 无对应商品信息
                return Triple(false, Error("订阅失败"), null)
            }

            // 判断返回的Count是否有问题
            if (count > (packet.content.size - 4) / 66) {
                return Triple(false, Error("订阅返回数量错误"), null)
            }

            // 获取商品订阅信息
            val quoteSubscriptGoodsIfs: ArrayList<MoQuoteSubscriptGoodsInfo> = ArrayList()
            try {
                for (i in 4 until packet.content.size step 66) {
                    quoteSubscriptGoodsIfs.add(
                        MoQuoteSubscriptGoodsInfo(
                            data = packet.content.sliceArray(i until i + 66)
                        )
                    )
                }
            } catch (e: Exception) {
                print(e)
            }

            return Triple(true, null, quoteSubscriptGoodsIfs)
        }

        /**
         * 分解实时行情数据
         * @param data ByteArray 实时行情二进制数据
         * @return List<Map<String, String>>? 分解后行情列表数据
         */
        fun splitQuoteGoods(data: ByteArray): List<Map<String, String>>? {
            // 可能会传入空数组
            if (data.isEmpty()) {
                return null
            }

            // 分解行正则
            val regRow = """10\s.*?11""".toRegex()
            // 分解单行 key 正则
            val regKey = """01\s.*?02""".toRegex()
            // 分解单行 value 正则
            val regValue = """02\s.*?01|02\s.*?11""".toRegex()

            // ByteArray to Hex string
            // FF 10 01 55 02 45 46 47 48 01 66 02 48 47 46 45 11 10 01 77 02 AA BB CC DD 11 00
            val hexString =
                data.joinToString(separator = " ") {
                    var str = Integer.toHexString(it.toInt())
                    if (str.length == 1) {
                        str = "0$str"
                    }
                    return@joinToString str
                }

            val goodsQuoteTiks = arrayListOf<Map<String, String>>()

            // 获取单行行情
            val rows = regRow.findAll(hexString).toList().flatMap(MatchResult::groupValues)
            for (row in rows) {
                // 单行行情： 0x10 ... 0x01 key 0x02 value 0x01 key 0x02 value ... 0x11
                // 10 01 55 02 45 46 47 48 01 66 02 48 47 46 45 11
                // 获取 key value 表列
                val keys = regKey.findAll(row).toList().flatMap(MatchResult::groupValues)
                val values = regValue.findAll(row).toList().flatMap(MatchResult::groupValues)

                // 将 key value 写入map中
                val goodsQuoteTik = mutableMapOf<String, String>()
                for (i in keys.indices) {
                    // 01 55 02
                    // Hex string to Int
                    val key = keys[i].substring(3, 5).toInt(16)

                    // 02 45 46 47 48 01
                    // 02 48 47 46 45 11
                    val tmpValue = values[i]
                    val value = String(
                        tmpValue.slice(3 until tmpValue.length - 3).split(" ")
                            .map { a -> a.toByte(16) }.toByteArray(), Charsets.US_ASCII
                    )
                    getQuoteTikField(goodsQuoteTik, key, value)
                }

                goodsQuoteTiks.add(goodsQuoteTik)
            }

            return goodsQuoteTiks
        }

        private fun getQuoteTikField(
            goodsQuoteTik: MutableMap<String, String>,
            key: Int,
            value: String
        ) {
            when (key) {
                0x56 -> {
                    goodsQuoteTik["exchangecode"] = value
                }
                0x21 -> {
                    goodsQuoteTik["goodscode"] = value
                }
                0x24 -> {
                    goodsQuoteTik["last"] = value
                }
                0x5b -> {
                    goodsQuoteTik["holdvolume"] = value
                }
                0x25 -> {
                    goodsQuoteTik["lastvolume"] = value
                }
                0x3c -> {
                    goodsQuoteTik["preholdvolume"] = value
                }
                0x32 -> {
                    goodsQuoteTik["presettle"] = value
                }
                0x33 -> {
                    goodsQuoteTik["settle"] = value
                }
                0x29 -> {
                    goodsQuoteTik["totalturnover"] = value
                }
                0x28 -> {
                    goodsQuoteTik["totalvolume"] = value
                }
                0x35 -> {
                    goodsQuoteTik["limithigh"] = value
                }
                0x36 -> {
                    goodsQuoteTik["limitlow"] = value
                }
                'l'.toInt() -> {
                    goodsQuoteTik["ask"] = value
                }
                'm'.toInt() -> {
                    goodsQuoteTik["ask2"] = value
                }
                'n'.toInt() -> {
                    goodsQuoteTik["ask3"] = value
                }
                'o'.toInt() -> {
                    goodsQuoteTik["ask4"] = value
                }
                'p'.toInt() -> {
                    goodsQuoteTik["ask5"] = value
                }
                'q'.toInt() -> {
                    goodsQuoteTik["askvolume"] = value
                }
                'r'.toInt() -> {
                    goodsQuoteTik["askvolume2"] = value
                }
                's'.toInt() -> {
                    goodsQuoteTik["askvolume3"] = value
                }
                't'.toInt() -> {
                    goodsQuoteTik["askvolume4"] = value
                }
                'u'.toInt() -> {
                    goodsQuoteTik["askvolume5"] = value
                }
                'b'.toInt() -> {
                    goodsQuoteTik["bid"] = value
                }
                'c'.toInt() -> {
                    goodsQuoteTik["bid2"] = value
                }
                'd'.toInt() -> {
                    goodsQuoteTik["bid3"] = value
                }
                'e'.toInt() -> {
                    goodsQuoteTik["bid4"] = value
                }
                'f'.toInt() -> {
                    goodsQuoteTik["bid5"] = value
                }
                'g'.toInt() -> {
                    goodsQuoteTik["bidvolume"] = value
                }
                'h'.toInt() -> {
                    goodsQuoteTik["bidvolume2"] = value
                }
                'i'.toInt() -> {
                    goodsQuoteTik["bidvolume3"] = value
                }
                'j'.toInt() -> {
                    goodsQuoteTik["bidvolume4"] = value
                }
                'k'.toInt() -> {
                    goodsQuoteTik["bidvolume5"] = value
                }
                ','.toInt() -> {
                    goodsQuoteTik["highest"] = value
                }
                '-'.toInt() -> {
                    goodsQuoteTik["lowest"] = value
                }
                '@'.toInt() -> {
                    goodsQuoteTik["date"] = value
                }
                'a'.toInt() -> {
                    goodsQuoteTik["time"] = value
                }
                '+'.toInt() -> {
                    goodsQuoteTik["preclose"] = value
                }
                '.'.toInt() -> {
                    goodsQuoteTik["opened"] = value
                }
                0x5c -> {
                    goodsQuoteTik["exerciseprice"] = value
                }
                0x7a -> {
                    goodsQuoteTik["inventory"] = value
                }
                0x7c -> {
                    goodsQuoteTik["exchangedate"] = value
                }
                0x70 -> {  // 1011 新增
                    goodsQuoteTik["strbidorder"] = value
                }
                0x71 -> {
                    goodsQuoteTik["strbidorder2"] = value
                }
                0x72 -> {
                    goodsQuoteTik["strbidorder3"] = value
                }
                0x73 -> {
                    goodsQuoteTik["strbidorder4"] = value
                }
                0x74 -> {
                    goodsQuoteTik["strbidorder5"] = value
                }
                0x75 -> {
                    goodsQuoteTik["straskorder"] = value
                }
                0x76 -> {
                    goodsQuoteTik["straskorder2"] = value
                }
                0x77 -> {
                    goodsQuoteTik["straskorder3"] = value
                }
                0x78 -> {
                    goodsQuoteTik["straskorder4"] = value
                }
                0x79 -> {
                    goodsQuoteTik["straskorder5"] = value
                }
                0x7d -> {
                    goodsQuoteTik["putoptionpremiums"] = value
                }
                0x7e -> {
                    goodsQuoteTik["putoptionpremiums2"] = value
                }
                0x80 -> {
                    goodsQuoteTik["putoptionpremiums3"] = value
                }
                0x81 -> {
                    goodsQuoteTik["putoptionpremiums4"] = value
                }
                0x82 -> {
                    goodsQuoteTik["putoptionpremiums5"] = value
                }
                0x83 -> {
                    goodsQuoteTik["calloptionpremiums"] = value
                }
                0x84 -> {
                    goodsQuoteTik["calloptionpremiums2"] = value
                }
                0x85 -> {
                    goodsQuoteTik["calloptionpremiums3"] = value
                }
                0x86 -> {
                    goodsQuoteTik["calloptionpremiums4"] = value
                }
                0x87 -> {
                    goodsQuoteTik["calloptionpremiums5"] = value
                }
                0x7b -> {
                    goodsQuoteTik["orderid "] = value
                }
                0x88 -> { // 非交易成交总量
                    goodsQuoteTik["nontotalvolume"] = value
                }
                0x89 -> { // 非交易总持仓量
                    goodsQuoteTik["nontotalholdervolume"] = value
                }
                0x8a -> { // 非交易成交总金额
                    goodsQuoteTik["nontotalturnover"] = value
                }
                0x8b -> { // 非交易成交总数
                    goodsQuoteTik["nontotallot"] = value
                }
                0x8c -> {
                    goodsQuoteTik["markprice"] = value
                }
                0x8d -> {
                    goodsQuoteTik["fundsrate"] = value
                }
                0x92 -> {
                    goodsQuoteTik["bidvolume6"] = value
                }
                0x93 -> {
                    goodsQuoteTik["bidvolume7"] = value
                }
                0x94 -> {
                    goodsQuoteTik["bidvolume8"] = value
                }
                0x95 -> {
                    goodsQuoteTik["bidvolume9"] = value
                }
                0x96 -> {
                    goodsQuoteTik["bidvolume10"] = value
                }
                0x97 -> {
                    goodsQuoteTik["ask6"] = value
                }
                0x98 -> {
                    goodsQuoteTik["ask7"] = value
                }
                0x99 -> {
                    goodsQuoteTik["ask8"] = value
                }
                0x9a -> {
                    goodsQuoteTik["ask9"] = value
                }
                0x9b -> {
                    goodsQuoteTik["ask10"] = value
                }
                0x9c -> {
                    goodsQuoteTik["askvolume6"] = value
                }
                0x9d -> {
                    goodsQuoteTik["askvolume7"] = value
                }
                0x9e -> {
                    goodsQuoteTik["askvolume8"] = value
                }
                0xa0 -> {
                    goodsQuoteTik["askvolume9"] = value
                }
                0xa1 -> {
                    goodsQuoteTik["askvolume10"] = value
                }
                0xa2 -> {
                    goodsQuoteTik["strbidorder6"] = value
                }
                0xa3 -> {
                    goodsQuoteTik["strbidorder7"] = value
                }
                0xa4 -> {
                    goodsQuoteTik["strbidorder8"] = value
                }
                0xa5 -> {
                    goodsQuoteTik["strbidorder9"] = value
                }
                0xa6 -> {
                    goodsQuoteTik["strbidorder10"] = value
                }
                0xa7 -> {
                    goodsQuoteTik["straskorder6"] = value
                }
                0xa8 -> {
                    goodsQuoteTik["straskorder7"] = value
                }
                0xa9 -> {
                    goodsQuoteTik["straskorder8"] = value
                }
                0xaa -> {
                    goodsQuoteTik["straskorder9"] = value
                }
                0xab -> {
                    goodsQuoteTik["straskorder10"] = value
                }
                0xac -> {
                    goodsQuoteTik["bid6"] = value
                }
                0xad -> {
                    goodsQuoteTik["bid7"] = value
                }
                0x8e -> {
                    goodsQuoteTik["bid8"] = value
                }
                0x90 -> {
                    goodsQuoteTik["bid9"] = value
                }
                0x91 -> {
                    goodsQuoteTik["bid10"] = value
                }
                0xae -> { // 买2的订单数量
                    goodsQuoteTik["bidordervol1"] = value
                }
                0xaf -> { // 买2的订单数量
                    goodsQuoteTik["bidordervol2"] = value
                }
                0xb0 -> { // 买3的订单数量
                    goodsQuoteTik["bidordervol3"] = value
                }
                0xb1 -> { // 买4的订单数量
                    goodsQuoteTik["bidordervol4"] = value
                }
                0xb2 -> { // 买5的订单数量
                    goodsQuoteTik["bidordervol5"] = value
                }
                0xb3 -> { // 买6的订单数量
                    goodsQuoteTik["bidordervol6"] = value
                }
                0xb4 -> { // 买7的订单数量
                    goodsQuoteTik["bidordervol7"] = value
                }
                0xb5 -> { // 买8的订单数量
                    goodsQuoteTik["bidordervol8"] = value
                }
                0xb6 -> { // 买9的订单数量
                    goodsQuoteTik["bidordervol9"] = value
                }
                0xb7 -> { // 买10的订单数量
                    goodsQuoteTik["bidordervol10"] = value
                }
                0xb8 -> { // 卖1的订单数量
                    goodsQuoteTik["askordervol1"] = value
                }
                0xb9 -> { // 卖2的订单数量
                    goodsQuoteTik["askordervol2"] = value
                }
                0xba -> { // 卖3的订单数量
                    goodsQuoteTik["askordervol3"] = value
                }
                0xbb -> { // 卖4的订单数量
                    goodsQuoteTik["askordervol4"] = value
                }
                0xbc -> { // 卖5的订单数量
                    goodsQuoteTik["askordervol5"] = value
                }
                0xbd -> { // 卖6的订单数量
                    goodsQuoteTik["askordervol6"] = value
                }
                0xbe -> { // 卖7的订单数量
                    goodsQuoteTik["askordervol7"] = value
                }
                0xbf -> { // 卖8的订单数量
                    goodsQuoteTik["askordervol8"] = value
                }
                0xc0 -> { // 卖9的订单数量
                    goodsQuoteTik["askordervol9"] = value
                }
                0xc1 -> { // 卖10的订单数量
                    goodsQuoteTik["askordervol10"] = value
                }
                0x59 -> { // 买经济盘数据
                    goodsQuoteTik["bidqueueinfo"] = value
                }
                0x5a -> { // 卖经济盘数据
                    goodsQuoteTik["askqueueinfo"] = value
                }
                0x6b -> {  // 交易类型
                    goodsQuoteTik["publictradetype"] = value
                }
            }
        }
    }
}