import { v4 } from 'uuid'
import { Package40 } from '@/utils/websocket/package'
import { FunCode } from '@/constants/funcode'
import { useLoginStore } from '@/stores'
import { subscribeListToByteArrary } from './build/encode'
import { parseSubscribeRsp } from './build/decode'
import Long from 'long'
import eventBus from '@/services/bus'
import socket from '../index'

export default new (class {
    /** 行情订阅列表 */
    private quoteSubscribeMap = new Map<string, string[]>()

    constructor() {
        // 接收行情服务断线重连成功通知
        eventBus.$on('QuoteServerReconnectNotify', () => {
            this.quoteSubscribe();
        })
    }

    /**
     * 向行情服务器发送请求
     * @param params 
     * @returns 
     */
    private send(params: Proto.QuoteReq[]) {
        const { loginId, token } = useLoginStore()
        const content = subscribeListToByteArrary(params, token, Long.fromNumber(loginId));

        return new Promise<Proto.QuoteRsp[]>((resolve, reject) => {
            socket.sendQuoteServer({
                data: {
                    rspCode: FunCode.QuoteSubscribeRsp,
                    payload: new Package40(FunCode.QuoteSubscribeReq, content)
                },
                success: (raw) => {
                    if (raw.content) {
                        parseSubscribeRsp(raw.content).then((res) => {
                            resolve(res);
                        }).catch(() => {
                            console.warn('报文解析失败', raw)
                            reject('报文解析失败')
                        })
                    } else {
                        reject('数据异常')
                    }
                },
                fail: (err) => {
                    console.error('服务器请求失败', err)
                    reject(err)
                }
            })
        })
    }

    /**
     * 开始行情订阅
     */
    private quoteSubscribe = () => {
        const subscribeData: Proto.QuoteReq[] = []

        this.quoteSubscribeMap.forEach((values) => {
            values.forEach((code) => {
                if (!subscribeData.some((e) => e.goodsCode === code)) {
                    subscribeData.push({
                        goodsCode: code,
                        exchangeCode: 250,
                        subState: 0
                    })
                }
            })
        })

        if (subscribeData.length) {
            console.log('开始行情订阅', subscribeData)
            this.send(subscribeData).then((res) => {
                if (res.length) {
                    console.log('行情订阅成功', res)
                } else {
                    console.error('行情订阅失败')
                }
            }).catch((err) => {
                console.error('行情订阅失败', err)
            })
        } else {
            // 没有订阅商品的时候，断开连接
            socket.closeQuoteServer()
        }
    }

    /**
     * 添加行情订阅
     * @param goodsCodes 
     * @param key 
     * @returns 
     */
    addSubscribe = (goodsCodes: string[], key?: string) => {
        const loginStore = useLoginStore()
        const uuid = key ?? v4()
        const value = this.quoteSubscribeMap.get(uuid) ?? []

        const start = () => {
            if (loginStore.token) {
                // 对相同 key 订阅的商品进行合并处理
                this.quoteSubscribeMap.set(uuid, [...value, ...goodsCodes])
                this.quoteSubscribe()
            }
        }

        return {
            uuid,
            start,
            stop: () => {
                const flag = this.quoteSubscribeMap.delete(uuid)
                if (flag) {
                    console.log('删除订阅', uuid)
                }
                if (loginStore.token) {
                    this.quoteSubscribe()
                }
                return flag
            },
        }
    }

    /**
     * 删除行情订阅
     * @param keys 
     */
    removeSubscribe = (...keys: string[]) => {
        if (keys.length) {
            keys.forEach((key) => {
                if (this.quoteSubscribeMap.delete(key)) {
                    console.log('删除订阅', key)
                }
            })
        } else {
            console.log('取消订阅')
            this.quoteSubscribeMap.clear()
        }
        this.quoteSubscribe()
    }
})