"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineLatestInit = exports.combineLatest = void 0;
const Observable_js_1 = require("../Observable.js");
const argsArgArrayOrObject_js_1 = require("../util/argsArgArrayOrObject.js");
const identity_js_1 = require("../util/identity.js");
const createObject_js_1 = require("../util/createObject.js");
const empty_js_1 = require("./empty.js");
function combineLatest(sources, resultSelector) {
    const parts = (0, argsArgArrayOrObject_js_1.arrayOrObject)(sources);
    if (!parts) {
        throw new TypeError('sources must be an array or object');
    }
    const { args: observables, keys } = parts;
    if (observables.length === 0) {
        return empty_js_1.EMPTY;
    }
    return new Observable_js_1.Observable(combineLatestInit(observables, keys
        ? (values) => (0, createObject_js_1.createObject)(keys, values)
        : resultSelector
            ? (values) => resultSelector(...values)
            : identity_js_1.identity));
}
exports.combineLatest = combineLatest;
function combineLatestInit(observables, valueTransform = identity_js_1.identity) {
    return (destination) => {
        const { length } = observables;
        const values = new Array(length);
        let active = length;
        let remainingFirstValues = length;
        for (let i = 0; i < length; i++) {
            const source = (0, Observable_js_1.from)(observables[i]);
            let hasFirstValue = false;
            source.subscribe((0, Observable_js_1.operate)({
                destination,
                next: (value) => {
                    values[i] = value;
                    if (!hasFirstValue) {
                        hasFirstValue = true;
                        remainingFirstValues--;
                    }
                    if (!remainingFirstValues) {
                        destination.next(valueTransform(Array.from(values)));
                    }
                },
                complete: () => {
                    if (!--active) {
                        destination.complete();
                    }
                },
            }));
        }
    };
}
exports.combineLatestInit = combineLatestInit;