import { MTP2WebSocket } from '@/utils/websocket'
import { SendMessage } from '@/utils/websocket/interface'
import { Package40, Package50 } from '@/utils/websocket/package'
import { timerInterceptor } from '@/utils/timer'
import { FunCode } from '@/constants/funcode'
import { parseReceivePush } from './quote/build/decode'
import protobuf from './trade/protobuf'
import { checkToken, stopCheckToken, checkTokenLoop } from '@/business/common'
import { useErrorInfoStore } from '@/stores/modules/errorInfo'
import service from '@/services'
import eventBus from '@/services/bus'

/**
 * 全局数据连接生命周期控制类
 */
export default new (class {
    /** 行情服务 */
    private readonly quoteServer = new MTP2WebSocket(Package40);
    /** 交易服务 */
    private readonly tradeServer = new MTP2WebSocket(Package50);

    constructor() {
        this.quoteServer.onPush = (p) => {
            const { mainClassNumber, content } = p;
            if (mainClassNumber === 65 && content) {
                const result = parseReceivePush(content);
                // 通知上层 行情推送
                eventBus.$emit('QuotePushNotify', result);
            }
        }

        this.quoteServer.onReconnect = () => {
            // 通知上层 重新订阅商品
            eventBus.$emit('QuoteServerReconnectNotify');
        }

        this.tradeServer.onPush = (p) => {
            const { getErrorInfoByCode } = useErrorInfoStore();
            const { funCode, content } = p;
            const delay = 1000; // 延迟推送消息，防止短时间内重复请求

            switch (funCode) {
                case FunCode.MoneyChangedNotify: {
                    timerInterceptor.debounce(() => {
                        // 通知上层 资金变动
                        eventBus.$emit('MoneyChangedNotify');
                    }, delay, funCode.toString())
                    break;
                }
                case FunCode.UserChangeNtf: {  // 账户信息变更通知
                    timerInterceptor.debounce(() => {
                        // 账户信息变更通知
                        eventBus.$emit('UserChangeNtf');
                    }, delay, funCode.toString())
                    break;
                } 
                case FunCode.LogoutRsp: {
                    // 通知上层 用户登出
                    protobuf.responseDecode<Proto.LogoutRsp>(FunCode[funCode], content).then(({ RetCode, RetDesc }) => {
                        const msg = getErrorInfoByCode(RetCode)
                        const error = (RetDesc || RetCode).toString();
                        eventBus.$emit('LogoutNotify', msg ?? error);
                    })
                    break;
                }
                default: {
                    if (funCode) {
                        console.warn('接收到未定义的通知', funCode);
                    }
                }
            }
        }

        this.tradeServer.onBeforeReconnect = () => {
            // 停止令牌效验
            stopCheckToken();
        }

        this.tradeServer.onReconnect = () => {
            // 重新进行令牌效验
            checkToken().then(() => checkTokenLoop());
        }
    }

    /** 主动连接行情服务 */
    async connectQuote() {
        const res = await service.onReady();
        await this.quoteServer.connect(res.quoteUrl);
    }

    /** 主动连接交易服务 */
    async connectTrade() {
        const res = await service.onReady();
        await this.tradeServer.connect(res.tradeUrl);
    }

    /** 向行情服务器发送请求 */
    async sendQuoteServer(msg: SendMessage<Package40>) {
        await this.connectQuote().catch((err) => {
            msg.fail && msg.fail(err);
        })
        return this.quoteServer.send(msg);
    }

    /** 向交易服务器发送请求 */
    async sendTradeServer(msg: SendMessage<Package50>) {
        await this.connectTrade().catch((err) => {
            msg.fail && msg.fail(err);
        })
        return this.tradeServer.send(msg);
    }

    /** 主动关闭行情服务 */
    closeQuoteServer() {
        this.quoteServer.close();
    }

    /** 主动关闭交易服务 */
    closeTradeServer() {
        this.tradeServer.close();
    }

    /** 关闭所有服务 */
    closeAll() {
        this.closeQuoteServer();
        this.closeTradeServer();
    }
})