"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.forkJoin = void 0;
const Observable_js_1 = require("../Observable.js");
const argsArgArrayOrObject_js_1 = require("../util/argsArgArrayOrObject.js");
const args_js_1 = require("../util/args.js");
const mapOneOrManyArgs_js_1 = require("../util/mapOneOrManyArgs.js");
const createObject_js_1 = require("../util/createObject.js");
const EmptyError_js_1 = require("../util/EmptyError.js");
function forkJoin(...args) {
    const resultSelector = (0, args_js_1.popResultSelector)(args);
    const { args: sources, keys } = (0, argsArgArrayOrObject_js_1.argsArgArrayOrObject)(args);
    const result = new Observable_js_1.Observable((destination) => {
        const { length } = sources;
        if (!length) {
            destination.complete();
            return;
        }
        const values = new Array(length);
        let remainingCompletions = length;
        let remainingEmissions = length;
        for (let sourceIndex = 0; sourceIndex < length; sourceIndex++) {
            let hasValue = false;
            (0, Observable_js_1.from)(sources[sourceIndex]).subscribe((0, Observable_js_1.operate)({
                destination,
                next: (value) => {
                    if (!hasValue) {
                        hasValue = true;
                        remainingEmissions--;
                    }
                    values[sourceIndex] = value;
                },
                complete: () => remainingCompletions--,
                finalize: () => {
                    if (!remainingCompletions || !hasValue) {
                        if (remainingEmissions === 0) {
                            destination.next(keys ? (0, createObject_js_1.createObject)(keys, values) : values);
                            destination.complete();
                        }
                        else {
                            destination.error(new EmptyError_js_1.EmptyError());
                        }
                    }
                },
            }));
        }
    });
    return resultSelector ? (0, mapOneOrManyArgs_js_1.mapOneOrManyArgs)(resultSelector)(result) : result;
}
exports.forkJoin = forkJoin;