"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.single = void 0;
const Observable_js_1 = require("../Observable.js");
const EmptyError_js_1 = require("../util/EmptyError.js");
const SequenceError_js_1 = require("../util/SequenceError.js");
const NotFoundError_js_1 = require("../util/NotFoundError.js");
function single(predicate) {
    return (source) => new Observable_js_1.Observable((destination) => {
        let hasValue = false;
        let singleValue;
        let seenValue = false;
        let index = 0;
        source.subscribe((0, Observable_js_1.operate)({
            destination,
            next: (value) => {
                seenValue = true;
                if (!predicate || predicate(value, index++, source)) {
                    hasValue && destination.error(new SequenceError_js_1.SequenceError('Too many matching values'));
                    hasValue = true;
                    singleValue = value;
                }
            },
            complete: () => {
                if (hasValue) {
                    destination.next(singleValue);
                    destination.complete();
                }
                else {
                    destination.error(seenValue ? new NotFoundError_js_1.NotFoundError('No matching values') : new EmptyError_js_1.EmptyError());
                }
            },
        }));
    });
}
exports.single = single;