var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
define(["require", "exports", '../Subscriber', '../util/tryCatch', '../util/errorObject', '../OuterSubscriber', '../util/subscribeToResult', '../util/Symbol_iterator'], function (require, exports, Subscriber_1, tryCatch_1, errorObject_1, OuterSubscriber_1, subscribeToResult_1, Symbol_iterator_1) {
    var isArray = Array.isArray;
    var ZipOperator = (function () {
        function ZipOperator(project) {
            this.project = project;
        }
        ZipOperator.prototype.call = function (subscriber) {
            return new ZipSubscriber(subscriber, this.project);
        };
        return ZipOperator;
    })();
    exports.ZipOperator = ZipOperator;
    var ZipSubscriber = (function (_super) {
        __extends(ZipSubscriber, _super);
        function ZipSubscriber(destination, project, values) {
            if (values === void 0) { values = Object.create(null); }
            _super.call(this, destination);
            this.index = 0;
            this.iterators = [];
            this.active = 0;
            this.project = (typeof project === 'function') ? project : null;
            this.values = values;
        }
        ZipSubscriber.prototype._next = function (value) {
            var iterators = this.iterators;
            var index = this.index++;
            if (isArray(value)) {
                iterators.push(new StaticArrayIterator(value));
            }
            else if (typeof value[Symbol_iterator_1.default] === 'function') {
                iterators.push(new StaticIterator(value[Symbol_iterator_1.default]()));
            }
            else {
                iterators.push(new ZipBufferIterator(this.destination, this, value, index));
            }
        };
        ZipSubscriber.prototype._complete = function () {
            var values = this.values;
            var iterators = this.iterators;
            var len = iterators.length;
            this.active = len;
            for (var i = 0; i < len; i++) {
                var iterator = iterators[i];
                if (iterator.stillUnsubscribed) {
                    iterator.subscribe(iterator, i);
                }
                else {
                    this.active--; // not an observable
                }
            }
        };
        ZipSubscriber.prototype.notifyInactive = function () {
            this.active--;
            if (this.active === 0) {
                this.destination.complete();
            }
        };
        ZipSubscriber.prototype.checkIterators = function () {
            var iterators = this.iterators;
            var len = iterators.length;
            var destination = this.destination;
            // abort if not all of them have values
            for (var i = 0; i < len; i++) {
                var iterator = iterators[i];
                if (typeof iterator.hasValue === 'function' && !iterator.hasValue()) {
                    return;
                }
            }
            var shouldComplete = false;
            var args = [];
            for (var i = 0; i < len; i++) {
                var iterator = iterators[i];
                var result = iterator.next();
                // check to see if it's completed now that you've gotten
                // the next value.
                if (iterator.hasCompleted()) {
                    shouldComplete = true;
                }
                if (result.done) {
                    destination.complete();
                    return;
                }
                args.push(result.value);
            }
            var project = this.project;
            if (project) {
                var result = tryCatch_1.default(project).apply(this, args);
                if (result === errorObject_1.errorObject) {
                    destination.error(errorObject_1.errorObject.e);
                }
                else {
                    destination.next(result);
                }
            }
            else {
                destination.next(args);
            }
            if (shouldComplete) {
                destination.complete();
            }
        };
        return ZipSubscriber;
    })(Subscriber_1.default);
    exports.ZipSubscriber = ZipSubscriber;
    var StaticIterator = (function () {
        function StaticIterator(iterator) {
            this.iterator = iterator;
            this.nextResult = iterator.next();
        }
        StaticIterator.prototype.hasValue = function () {
            return true;
        };
        StaticIterator.prototype.next = function () {
            var result = this.nextResult;
            this.nextResult = this.iterator.next();
            return result;
        };
        StaticIterator.prototype.hasCompleted = function () {
            var nextResult = this.nextResult;
            return nextResult && nextResult.done;
        };
        return StaticIterator;
    })();
    var StaticArrayIterator = (function () {
        function StaticArrayIterator(array) {
            this.array = array;
            this.index = 0;
            this.length = 0;
            this.length = array.length;
        }
        StaticArrayIterator.prototype[Symbol_iterator_1.default] = function () {
            return this;
        };
        StaticArrayIterator.prototype.next = function (value) {
            var i = this.index++;
            var array = this.array;
            return i < this.length ? { value: array[i], done: false } : { done: true };
        };
        StaticArrayIterator.prototype.hasValue = function () {
            return this.array.length > this.index;
        };
        StaticArrayIterator.prototype.hasCompleted = function () {
            return this.array.length === this.index;
        };
        return StaticArrayIterator;
    })();
    var ZipBufferIterator = (function (_super) {
        __extends(ZipBufferIterator, _super);
        function ZipBufferIterator(destination, parent, observable, index) {
            _super.call(this, destination);
            this.parent = parent;
            this.observable = observable;
            this.index = index;
            this.stillUnsubscribed = true;
            this.buffer = [];
            this.isComplete = false;
        }
        ZipBufferIterator.prototype[Symbol_iterator_1.default] = function () {
            return this;
        };
        // NOTE: there is actually a name collision here with Subscriber.next and Iterator.next
        //    this is legit because `next()` will never be called by a subscription in this case.
        ZipBufferIterator.prototype.next = function () {
            var buffer = this.buffer;
            if (buffer.length === 0 && this.isComplete) {
                return { done: true };
            }
            else {
                return { value: buffer.shift(), done: false };
            }
        };
        ZipBufferIterator.prototype.hasValue = function () {
            return this.buffer.length > 0;
        };
        ZipBufferIterator.prototype.hasCompleted = function () {
            return this.buffer.length === 0 && this.isComplete;
        };
        ZipBufferIterator.prototype.notifyComplete = function () {
            if (this.buffer.length > 0) {
                this.isComplete = true;
                this.parent.notifyInactive();
            }
            else {
                this.destination.complete();
            }
        };
        ZipBufferIterator.prototype.notifyNext = function (outerValue, innerValue, outerIndex, innerIndex) {
            this.buffer.push(innerValue);
            this.parent.checkIterators();
        };
        ZipBufferIterator.prototype.subscribe = function (value, index) {
            this.add(subscribeToResult_1.default(this, this.observable, this, index));
        };
        return ZipBufferIterator;
    })(OuterSubscriber_1.default);
});
//# sourceMappingURL=zip-support.js.map