"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppClient = void 0;
const events_1 = require("events");
const enum_1 = require("@/@types/enum");
const middlewares_1 = require("@/middlewares");
const cdp_1 = require("@/utils/cdp");
const log_1 = require("@/utils/log");
const middleware_1 = require("@/utils/middleware");
const filteredLog = new log_1.Logger('filtered', enum_1.WinstonColor.Yellow);
const downwardLog = new log_1.Logger('↓↓↓', enum_1.WinstonColor.BrightRed);
const upwardLog = new log_1.Logger('↑↑↑', enum_1.WinstonColor.BrightGreen);
/**
 * app client 通道，负责调试协议至 app 端的收发。目前包括三个通道，分别由三个子类实现：
 *    - tunnel 通道：c++ addon 实现
 *    - ws 通道：手 Q 采用此通道
 *    - IWDP 通道：TDF iOS 采用此通道
 **/
class AppClient extends events_1.EventEmitter {
    constructor(id, { useAllDomain = true, acceptDomains, ignoreDomains = [], middleWareManager, urlParsedContext, platform, }) {
        super();
        this.isClosed = false;
        this.acceptDomains = cdp_1.CDP_DOMAIN_LIST;
        this.ignoreDomains = [];
        this.useAllDomain = true;
        this.msgIdMap = new Map();
        this.id = id;
        this.useAllDomain = useAllDomain;
        this.acceptDomains = acceptDomains;
        this.ignoreDomains = ignoreDomains;
        this.middleWareManager = middleWareManager;
        this.urlParsedContext = urlParsedContext;
        this.platform = platform;
    }
    /**
     * 调试协议经过中间件的适配后，上行发送至 app 端
     */
    sendToApp(msg) {
        if (!this.filter(msg)) {
            filteredLog.info(`'${msg.method}' is filtered in app client type: ${this.constructor.name}`);
            return Promise.reject(1 /* DomainFiltered */);
        }
        const { method } = msg;
        this.msgIdMap.set(msg.id, {
            method: msg.method,
        });
        const middlewareList = this.getMiddlewareList(enum_1.MiddlewareType.Upward, method);
        // 上行的具体协议的处理交给中间件去适配，最后分发到 app 端
        return this.middlewareMessageHandler(middlewareList, msg);
    }
    destroy() { }
    /**
     * 下行协议适配 handler
     */
    downwardMessageHandler(msg) {
        var _a;
        try {
            if ('id' in msg && 'result' in msg) {
                const cache = this.msgIdMap.get(msg.id);
                if (cache === null || cache === void 0 ? void 0 : cache.method)
                    msg.method = cache.method;
                else
                    downwardLog.warn("method doesn't exist %j", msg);
            }
            const { method } = msg;
            const middlewareList = this.getMiddlewareList(enum_1.MiddlewareType.Downward, method);
            return this.middlewareMessageHandler(middlewareList, msg);
        }
        catch (e) {
            downwardLog.error(`app client on message error: %s`, (_a = e) === null || _a === void 0 ? void 0 : _a.stack);
            return Promise.reject(e);
        }
    }
    /**
     * 通过中间件处理上下行消息
     */
    middlewareMessageHandler(middlewareList, msgBeforeAdapter) {
        // 创建中间件上下文，中间件中可以通过调用 sendToApp, sendToDevtools 将调试协议分发到接收端
        const middlewareContext = Object.assign(Object.assign({}, this.urlParsedContext), { msg: msgBeforeAdapter, sendToApp: (msg) => {
                if (!msg.id) {
                    msg.id = middlewares_1.requestId.create();
                }
                this.msgIdMap.set(msg.id, {
                    method: msg.method,
                });
                upwardLog.info('%s sendToApp %j', this.constructor.name, msg);
                return this.sendHandler(Object.assign({}, msg));
            }, sendToDevtools: (msg) => {
                downwardLog.info('%s sendToDevtools %s %s', this.constructor.name, msg.id || '', msg.method);
                return this.emitMessageToDevtools(Object.assign({}, msg));
            } });
        return middleware_1.composeMiddlewares(middlewareList)(middlewareContext);
    }
    /**
     * 协议下行发送至 devtools 端
     */
    emitMessageToDevtools(msg) {
        if (!msg)
            return Promise.reject(3 /* EmptyCommand */);
        this.emit("message" /* Message */, msg);
        if ('id' in msg) {
            this.msgIdMap.delete(msg.id);
        }
        return Promise.resolve(msg);
    }
    /**
     * 上行协议 filter，通过才放行
     */
    filter(msg) {
        if (this.useAllDomain)
            return true;
        const { method } = msg;
        const domain = cdp_1.getDomain(method);
        if (this.ignoreDomains.length) {
            const isIgnoreDomain = this.ignoreDomains.indexOf(domain) !== -1 || this.ignoreDomains.indexOf(method) !== -1;
            return !isIgnoreDomain;
        }
        const isAcceptDomain = this.acceptDomains.indexOf(domain) !== -1 || this.acceptDomains.indexOf(method) !== -1;
        return isAcceptDomain;
    }
    /**
     * 根据调试协议查询注册的中间件列表
     */
    getMiddlewareList(type, method) {
        let middlewareList = {
            [enum_1.MiddlewareType.Upward]: this.middleWareManager.upwardMiddleWareListMap,
            [enum_1.MiddlewareType.Downward]: this.middleWareManager.downwardMiddleWareListMap,
        }[type][method];
        if (!middlewareList)
            middlewareList = [];
        if (!Array.isArray(middlewareList))
            middlewareList = [middlewareList];
        return [...middlewareList, type === enum_1.MiddlewareType.Upward ? middlewares_1.defaultUpwardMiddleware : middlewares_1.defaultDownwardMiddleware];
    }
}
exports.AppClient = AppClient;
