/*
 * market-data.ts - the MarketData client (行情).
 *
 * EventEmitter for streaming pushes (rtn-depth-market-data, ...) + Promise for
 * request/response (login). Event codes mirror src/native/mdspi.h.
 */
import { native } from "./native-binding.js";
import { CtpClient } from "./client.js";
const MD_BASE = 0x1000;
const MD_EVENTS = new Map([
    [MD_BASE + 1, "front-connected"],
    [MD_BASE + 2, "front-disconnected"],
    [MD_BASE + 3, "heart-beat-warning"],
    [MD_BASE + 4, "rsp-user-login"],
    [MD_BASE + 5, "rsp-user-logout"],
    [MD_BASE + 6, "rsp-qry-multicast-instrument"],
    [MD_BASE + 7, "rsp-error"],
    [MD_BASE + 8, "rsp-sub-market-data"],
    [MD_BASE + 9, "rsp-unsub-market-data"],
    [MD_BASE + 10, "rsp-sub-for-quote"],
    [MD_BASE + 11, "rsp-unsub-for-quote"],
    [MD_BASE + 12, "rtn-depth-market-data"],
    [MD_BASE + 13, "rtn-for-quote"],
]);
/** Market-data event names (symbolic; plain strings also work). */
export var MarketDataEvent;
(function (MarketDataEvent) {
    MarketDataEvent["FrontConnected"] = "front-connected";
    MarketDataEvent["FrontDisconnected"] = "front-disconnected";
    MarketDataEvent["HeartBeatWarning"] = "heart-beat-warning";
    MarketDataEvent["RspUserLogin"] = "rsp-user-login";
    MarketDataEvent["RspUserLogout"] = "rsp-user-logout";
    MarketDataEvent["RspQryMulticastInstrument"] = "rsp-qry-multicast-instrument";
    MarketDataEvent["RspError"] = "rsp-error";
    MarketDataEvent["RspSubMarketData"] = "rsp-sub-market-data";
    MarketDataEvent["RspUnSubMarketData"] = "rsp-unsub-market-data";
    MarketDataEvent["RspSubForQuote"] = "rsp-sub-for-quote";
    MarketDataEvent["RspUnSubForQuote"] = "rsp-unsub-for-quote";
    MarketDataEvent["RtnDepthMarketData"] = "rtn-depth-market-data";
    MarketDataEvent["RtnForQuote"] = "rtn-for-quote";
})(MarketDataEvent || (MarketDataEvent = {}));
export class MarketData extends CtpClient {
    constructor(flowPath, fronts) {
        super(new native.MarketData(flowPath, fronts), native.__layoutData(), MD_EVENTS);
        // SimNow's MD login/logout responses come back with requestId 0. Scope the
        // id-0 fallback to those two events (which are never concurrent) so an id-0
        // sub/unsub/error response can't hijack a pending login()/logout().
        this.zeroIdFallbackEvents.add(MD_BASE + 4); // rsp-user-login
        this.zeroIdFallbackEvents.add(MD_BASE + 5); // rsp-user-logout
        this.start();
    }
    getApiVersion() {
        return this.native.getApiVersion();
    }
    getTradingDay() {
        return this.native.getTradingDay();
    }
    /** Subscribe to depth market data. Returns the CTP send code (0 = ok). */
    subscribe(instrumentIds) {
        return this.native.subscribeMarketData(instrumentIds);
    }
    unsubscribe(instrumentIds) {
        return this.native.unsubscribeMarketData(instrumentIds);
    }
    subscribeForQuote(instrumentIds) {
        return this.native.subscribeForQuoteRsp(instrumentIds);
    }
    unsubscribeForQuote(instrumentIds) {
        return this.native.unsubscribeForQuoteRsp(instrumentIds);
    }
    /** Log in; resolves with the login response (or rejects on CTP error). */
    login(req = {}) {
        return this.request((id) => this.native.reqUserLogin(req, id), true);
    }
    logout(req = {}) {
        return this.request((id) => this.native.reqUserLogout(req, id), true);
    }
    armedTrader;
    /** Route this market data's ticks to a Trader's armed triggers (see Trader.arm).
     *  A MarketData feeds exactly one Trader's registry; attaching a second,
     *  different Trader throws rather than silently stealing the feed. */
    attachArm(trader) {
        if (this.armedTrader && this.armedTrader !== trader) {
            throw new Error("this MarketData already feeds another Trader's armed triggers");
        }
        this.armedTrader = trader;
        this.native._attachArm(trader._armRegistry());
    }
    /** @internal test-only: inject a synthetic depth tick into the ring. Optional
     *  bid/ask override the defaults (3499/3501) so tests can drive edge prices
     *  (e.g. a DBL_MAX no-bid sentinel) through the real arm/onTick path. */
    _injectTestTick(bid, ask) {
        this.native._injectTestTick(bid, ask);
    }
    /** @internal test-only: spawn a background producer thread that pushes `n`
     *  synthetic ticks into the ring (cross-thread doorbell stress). Each tick's
     *  requestId carries its sequence number. */
    _burstTicks(n, jitterUs = 0) {
        this.native._burstTicks(n, jitterUs);
    }
    on(event, cb) {
        return super.on(event, cb);
    }
}
//# sourceMappingURL=market-data.js.map