package cn.muchinfo.rma.business.quote

import cn.muchinfo.rma.business.account.adapter.AccountAdapter
import cn.muchinfo.rma.business.quote.adapter.QuoteAdapter
import cn.muchinfo.rma.global.GlobalDataCollection
import cn.muchinfo.rma.netcore.packet.Packet40
import cn.muchinfo.rma.netcore.packet.Packet50
import cn.muchinfo.rma.netcore.socket.Callback
import cn.muchinfo.rma.protobuf.classNumber.ClassNumber
import cn.muchinfo.rma.view.MyApplication
import cn.muchinfo.rma.view.autoWidget.guard
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentSkipListSet

/**
 * 行情管理类
 */
class QuoteManager {
    /** 当前已订阅行情商品列表 */
    private var currentGoodsSet = ConcurrentSkipListSet<String>()

    /** 订阅Map */
    private var subcriptMap = ConcurrentHashMap<String, ConcurrentSkipListSet<String>>()

    /**
     * 按需订阅行情添加订阅商品
     * @param tag String 订阅方标志，一般使用UUID生成的唯一码
     * @param goodsCodeSet ConcurrentSkipListSet<String> 待订阅商品代码列表
     * @param callback Function2<[@kotlin.ParameterName] Boolean, [@kotlin.ParameterName] Error?, Unit>? 回调
     */
    fun addSubscriptQuote(
        tag: String,
        goodsCodeSet: Set<String>,
        callback: ((isCompleted: Boolean, err: Error?) -> Unit)?
    ) {
        val app = MyApplication.getInstance().guard {
            if (callback != null) {
                callback(false, Error("Application未初始化"))
            }
            return
        }
        val quoteSocketManager = app.quoteSocketManager.guard {
            if (callback != null) {
                callback(false, Error("行情链路未初始化"))
            }
            return
        }
        // 判断当前是否已经连接行情链路
        if (quoteSocketManager.connState != 2) {
            if (callback != null) {
                callback(false, Error("行情链路未连接"))
            }
            return
        }

        // 添加到当前订阅列表中
        subcriptMap[tag] = ConcurrentSkipListSet(goodsCodeSet)
        val addSet = HashSet<String>()
        for (item in goodsCodeSet) {
            if (item !in currentGoodsSet) {
                addSet.add(item)
            }
        }
        // 判断是否要重新订阅
        if (addSet.count() > 0) {
            currentGoodsSet.addAll(addSet)
            // 重新订阅行情
            subscriptQuote(callback)
        }
    }

    /**
     * 按需订阅行情移除订阅商品
     * @param tag String 订阅方标志，一般使用UUID生成的唯一码
     */
    fun removeSubscriptQuote(tag: String) {
        val app = MyApplication.getInstance().guard {
            return
        }
        val quoteSocketManager = app.quoteSocketManager.guard {
            return
        }
        // 判断当前是否已经连接行情链路
        if (quoteSocketManager.connState != 2) {
            return
        }

        if (subcriptMap.contains(tag)) {
            subcriptMap.remove(tag)
            // 构建当前需订阅的商品列表
            val needSet = HashSet<String>()
            for (items in subcriptMap.values) {
                for (goodsCode in items) {
                    if (goodsCode !in needSet) {
                        needSet.add(goodsCode)
                    }
                }
            }
            // 判断与当前订阅列表是否一样
            if (currentGoodsSet != needSet) {
                currentGoodsSet.clear()
                currentGoodsSet.addAll(needSet)

                // 重新订阅行情
                subscriptQuote(null)
            }
        }
    }

    /**
     * 订阅商品实时行情
     * @param callback Function2<[@kotlin.ParameterName] Boolean, [@kotlin.ParameterName] Error?, Unit>?
     */
    fun subscriptQuote(callback: ((isCompleted: Boolean, err: Error?) -> Unit)?) {
        // 当前是否已经登陆
        val loginRsp = GlobalDataCollection.instance?.loginRsp.guard {
            if (callback != null) {
                callback(false, Error("当前未登录"))
            }
            return
        }

        val reqPacket = QuoteAdapter.buildSubscriptPacket(
            currentGoodsSet.toSet(),
            loginRsp.token,
            loginRsp.loginID
        )
        // 发送订阅请求
        val quoteSocketManager = MyApplication.getInstance()?.quoteSocketManager
        quoteSocketManager?.send(
            reqPacket,
            ClassNumber.MainClassNumber_Quota_SubscriptRsp,
            object :
                Callback<Packet40> {
                override fun onSuccess(rsp: Packet40?) {
                    val rst = QuoteAdapter.analySubscriptRsp(rsp!!)
                    if (!rst.first) {
                        // 订阅失败
                        if (callback != null) {
                            callback(false, Error("行情订阅失败"))
                        }
                    }

                    // 订阅成功后通知网络开始发送心跳
                    quoteSocketManager.startBeatTime()
                    // 通知网络可进行断网重连
                    quoteSocketManager.canReconnect = true

                    if (callback != null) {
                        callback(true, null)
                    }
                }

                override fun onFail(err: java.lang.Error?) {
                    if (callback != null) {
                        callback(false, err)
                    }
                }
            })
    }
}