"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.throttle = void 0;
const Observable_js_1 = require("../Observable.js");
function throttle(durationSelector, config) {
    return (source) => new Observable_js_1.Observable((destination) => {
        const { leading = true, trailing = false } = config ?? {};
        let hasValue = false;
        let sendValue = null;
        let throttled = null;
        let isComplete = false;
        const endThrottling = () => {
            throttled?.unsubscribe();
            throttled = null;
            if (trailing) {
                send();
                isComplete && destination.complete();
            }
        };
        const cleanupThrottling = () => {
            throttled = null;
            isComplete && destination.complete();
        };
        const startThrottle = (value) => (throttled = (0, Observable_js_1.from)(durationSelector(value)).subscribe((0, Observable_js_1.operate)({ destination, next: endThrottling, complete: cleanupThrottling })));
        const send = () => {
            if (hasValue) {
                hasValue = false;
                const value = sendValue;
                sendValue = null;
                destination.next(value);
                !isComplete && startThrottle(value);
            }
        };
        source.subscribe((0, Observable_js_1.operate)({
            destination,
            next: (value) => {
                hasValue = true;
                sendValue = value;
                !(throttled && !throttled.closed) && (leading ? send() : startThrottle(value));
            },
            complete: () => {
                isComplete = true;
                !(trailing && hasValue && throttled && !throttled.closed) && destination.complete();
            },
        }));
    });
}
exports.throttle = throttle;