// Inspired by https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.promise.all-settled.js
// Will only work for arrays or type which have implemented a forEach method
// Licensed under the MIT License

Promise.allSettled = Promise.allSettled || function () {
    var Deferred = function () {
        this.promise = new Promise(function(_resolve, _reject)  {
            this.resolve = _resolve;
            this.reject = _reject;
        }.bind(this));
    };
    
    function allSettled(_promises) {
        var deferred = new Deferred();
        var resolve = deferred.resolve;
        var reject = deferred.reject;
        var remaining = 1;
        var values = [];
        try {
        	_promises.forEach(function (_promise, _index) {
				var alreadyCalled = false;
				values.push(undefined);
				remaining++;
				Promise.resolve(_promise).then(function(_value) {
					if (alreadyCalled) {
						return;
					}
					alreadyCalled = true;
					values[_index] = { status: 'fulfilled', value: _value };
					remaining--;
					if (remaining === 0) {
						resolve(values);
					}
				}, function(_err) {
					if (alreadyCalled) {
						return;
					}
					values[_index] = { status: 'rejected', reason: _err };
					remaining--;
					if (remaining === 0) {
						resolve(values);
					}
				});
			});
            remaining--;
            if (remaining === 0) {
                resolve(values);
            }
        } catch (_err) {
            reject(_err);
        }
        return deferred.promise;
    }
    
    return allSettled;
}();
