"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.constructSubscriptionMarble = void 0;
const ObservableMarbleToken_1 = require("../marbles/ObservableMarbleToken");
const SubscriptionMarbleToken_1 = require("../marbles/SubscriptionMarbleToken");
const MAX_FRAME_LENGTH = 30;
/**
 * @internal
 */
const constructSubscriptionMarble = ({ subscribedFrame, unsubscribedFrame, }) => {
    const marble = Array.from(Array(MAX_FRAME_LENGTH + 1)).map(() => ObservableMarbleToken_1.ObservableMarbleToken.TIMEFRAME);
    let frameString = '';
    let subscribeExpandingTimeFrame = Number.POSITIVE_INFINITY;
    if (subscribedFrame !== Number.POSITIVE_INFINITY) {
        if (subscribedFrame > MAX_FRAME_LENGTH) {
            //replace start of marble into `---...${n}...---^`, where
            //n makes subscription frame with prefix, postfix expand token (3, 3 - 6 in total)
            //then remain whole marble length as max frame length
            subscribeExpandingTimeFrame = subscribedFrame - 6;
            marble.unshift(...Array.from(`---...${subscribeExpandingTimeFrame}...---^`));
            const idx = marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE) + 1;
            while (marble.length > MAX_FRAME_LENGTH + 1) {
                marble.splice(idx, 1);
            }
        }
        else {
            marble[subscribedFrame] = SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE;
        }
        const frameIdx = marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE);
        while (frameString.length < frameIdx) {
            frameString += ' ';
        }
        frameString += subscribedFrame;
    }
    if (unsubscribedFrame !== Number.POSITIVE_INFINITY) {
        if (unsubscribedFrame > MAX_FRAME_LENGTH) {
            const isSubscribed = subscribedFrame !== Number.POSITIVE_INFINITY;
            const remaningFrame = isSubscribed
                ? MAX_FRAME_LENGTH - marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE) - 1
                : MAX_FRAME_LENGTH;
            const unsubscribeExpandTimeFrame = isSubscribed
                ? unsubscribedFrame - subscribedFrame + 1 - remaningFrame + 6
                : unsubscribedFrame + 1 - MAX_FRAME_LENGTH + 6;
            let expandedFrame = `...${unsubscribeExpandTimeFrame}...---!`;
            let count = expandedFrame.length;
            // If in-range subscription collides to expanding token, preserve it though it increases length
            const availableTimeFrame = MAX_FRAME_LENGTH - count;
            if (marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE) > availableTimeFrame) {
                const exceedFrameCount = marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE) - availableTimeFrame;
                expandedFrame = `...${unsubscribeExpandTimeFrame - exceedFrameCount}...---!`;
            }
            count = expandedFrame.length;
            while (count-- > 0 && marble[marble.length - 1] !== SubscriptionMarbleToken_1.SubscriptionMarbleToken.SUBSCRIBE) {
                marble.pop();
            }
            marble.push(...Array.from(expandedFrame));
        }
        else {
            marble[unsubscribedFrame] = SubscriptionMarbleToken_1.SubscriptionMarbleToken.UNSUBSCRIBE;
        }
        const frameIdx = marble.lastIndexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.UNSUBSCRIBE);
        while (frameString.length < frameIdx) {
            frameString += ' ';
        }
        frameString += unsubscribedFrame;
        //strip timeframe after unsubscription
        marble.splice(marble.indexOf(SubscriptionMarbleToken_1.SubscriptionMarbleToken.UNSUBSCRIBE) + 1);
    }
    const marbleString = marble.join('');
    return { marbleString, frameString };
};
exports.constructSubscriptionMarble = constructSubscriptionMarble;
//# sourceMappingURL=constructSubscriptionMarble.js.map