"use strict";
/*!
  Copyright 2018 Ron Buckton (rbuckton@chronicles.org)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
if (!hasNativeSymbol() || !hasNativeCollections()) {
    installShims(getGlobal());
}
function hasNativeSymbol() {
    return typeof Symbol === "function";
}
function hasNativeCollections() {
    return typeof Map !== "undefined"
        && typeof Set !== "undefined"
        && typeof WeakMap !== "undefined"
        && typeof WeakSet !== "undefined";
}
function getGlobal() {
    if (typeof global !== "undefined")
        return global;
    if (typeof self !== "undefined")
        return self;
    if (typeof window !== "undefined")
        return window;
    throw new Error("Global object not found");
}
function installShims(global) {
    var H = newUint32Array(5);
    var W = newUint8Array(80);
    var B = newUint8Array(64);
    if (!hasNativeSymbol()) {
        installSymbolShim();
    }
    if (!hasNativeCollections()) {
        installCollectionsShim();
    }
    function uuid(name, ns) {
        try {
            var offset_1 = 0, buffer_1 = B, kind = 0x40;
            if (ns) {
                name = String(name);
                var uuidSize = 16, blockSize = 64;
                var textSize = name.length;
                var messageSize = uuidSize + textSize * 2;
                var finalBlockSize = messageSize % blockSize;
                var padSize = (finalBlockSize < blockSize - 8 - 1 ? blockSize : blockSize * 2) - finalBlockSize;
                var byteLength = messageSize + padSize;
                if (byteLength > blockSize)
                    buffer_1 = newUint8Array(byteLength);
                for (var i = 0; i < uuidSize; ++i)
                    buffer_1[i] = ns[i] & 0xff;
                for (var i = 0; i < textSize; ++i)
                    setUint(buffer_1, uuidSize + i * 2, 2, name.charCodeAt(i));
                buffer_1[messageSize] = 0x80;
                setUint(buffer_1, byteLength - 4, 4, messageSize * 8);
                H[0] = 0x67452301, H[1] = 0xefcdab89, H[2] = 0x98badcfe, H[3] = 0x10325476, H[4] = 0xc3d2e1f0;
                for (var offset_2 = 0; offset_2 < byteLength; offset_2 += blockSize) {
                    var a = H[0], b = H[1], c = H[2], d = H[3], e = H[4];
                    for (var i = 0; i < 80; ++i) {
                        if (i < 16) {
                            var x = offset_2 + i * 4;
                            W[i] = buffer_1[x] << 24 | buffer_1[x + 1] << 16 | buffer_1[x + 2] << 8 | buffer_1[x + 3];
                        }
                        else {
                            var x = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
                            W[i] = (x << 1 | x >>> 31) >>> 0;
                        }
                        var t = (a << 5 | a >>> 27) >>> 0 + e + W[i];
                        if (i < 20)
                            t += ((b & c) | (~b & d)) + 0x5A827999;
                        else if (i < 40)
                            t += (b ^ c ^ d) + 0x6ED9EBA1;
                        else if (i < 60)
                            t += ((b & c) | (b & d) | (c & d)) + 0x8F1BBCDC;
                        else
                            t += (b ^ c ^ d) + 0xCA62C1D6;
                        e = d, d = c, c = (b << 30 | b >>> 2) >>> 0, b = a, a = t;
                    }
                    H[0] += a, H[1] += b, H[2] += c, H[3] += d, H[4] += e;
                }
                for (var i = 0; i < 5; ++i)
                    setUint(buffer_1, i * 4, 4, H[i]);
                kind = 0x41;
            }
            else {
                for (var i = 0; i < 16; i += 4)
                    setUint(buffer_1, i, 4, (Math.random() * 0xffffffff));
            }
            buffer_1[6] = buffer_1[6] & 0x4f | kind;
            buffer_1[8] = buffer_1[8] & 0xbf | 0x80;
            return "DDDDDDDD-DDDD-DDDD-DDDD-DDDDDDDDDDDD".replace(/DD/g, function () { return (buffer_1[offset_1] < 16 ? "0" : "") + buffer_1[offset_1++].toString(16); });
        }
        finally {
            clear(H);
            clear(W);
            clear(B);
        }
    }
    function setUint(buffer, offset, size, value) {
        for (var i = 0; i < size; ++i)
            buffer[offset + i] = (value >>> ((size - i - 1) * 8)) & 0xff;
    }
    function newUint32Array(size) {
        return typeof Uint32Array === "function" ? new Uint32Array(size) : clear(new Array(size));
    }
    function newUint8Array(size) {
        return typeof Uint8Array === "function" ? new Uint8Array(size) : clear(new Array(size));
    }
    function clear(buffer) {
        if (typeof buffer.fill === "function") {
            buffer.fill(0);
        }
        else {
            for (var i = 0; i < buffer.length; i++)
                buffer[i] = 0;
        }
        return buffer;
    }
    function installSymbolShim() {
        var e_1, _a;
        var SYMBOL_BUILTIN = [
            // es2015
            "hasInstance",
            "isConcatSpreadable",
            "iterator",
            "match",
            "replace",
            "search",
            "species",
            "split",
            "toPrimitive",
            "toStringTag",
            "unscopables",
            // es2018
            "asyncIterator"
        ];
        var SYMBOL_GLOBAL_NS = [0x96, 0x89, 0x6a, 0xf3, 0xaf, 0xd9, 0x4e, 0xcc, 0xad, 0x7e, 0x53, 0x89, 0xd6, 0xe8, 0x21, 0x73];
        var SYMBOL_INTERNAL_NS = [0x96, 0x89, 0x6a, 0xf3, 0xaf, 0xd9, 0x4e, 0xcc, 0xad, 0x7e, 0x53, 0x89, 0xd6, 0xe8, 0x21, 0x75];
        var SYMBOL_PARSER = /^Symbol\((.*?)\)@@(urn:uuid:[a-fA-F\d]{8}-[a-fA-F\d]{4}-[a-fA-F\d]{4}-[a-fA-F\d]{4}-[a-fA-F\d]{12})$/;
        var Symbol = function (description) {
            if (this instanceof Symbol)
                throw new TypeError("Symbol is not a constructor");
            return symbolFor(description);
        };
        Object.defineProperty(Symbol, "for", {
            configurable: true, writable: true,
            value: function (key) { return symbolFor(String(key), SYMBOL_GLOBAL_NS); }
        });
        Object.defineProperty(Symbol, "keyFor", {
            configurable: true, writable: true,
            value: function (symbol) {
                var match = SYMBOL_PARSER.exec(symbol);
                return match && symbolFor(match[1], SYMBOL_GLOBAL_NS) === symbol ? match[1] : undefined;
            }
        });
        try {
            for (var SYMBOL_BUILTIN_1 = tslib_1.__values(SYMBOL_BUILTIN), SYMBOL_BUILTIN_1_1 = SYMBOL_BUILTIN_1.next(); !SYMBOL_BUILTIN_1_1.done; SYMBOL_BUILTIN_1_1 = SYMBOL_BUILTIN_1.next()) {
                var name = SYMBOL_BUILTIN_1_1.value;
                Object.defineProperty(Symbol, name, {
                    value: symbolFor("Symbol." + name, SYMBOL_INTERNAL_NS)
                });
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (SYMBOL_BUILTIN_1_1 && !SYMBOL_BUILTIN_1_1.done && (_a = SYMBOL_BUILTIN_1.return)) _a.call(SYMBOL_BUILTIN_1);
            }
            finally { if (e_1) throw e_1.error; }
        }
        global.Symbol = Symbol;
        function symbolFor(description, ns) {
            description = ns === undefined && description === undefined ? "" : String(description);
            return "Symbol(" + description + ")@@urn:uuid:" + uuid(description, ns);
        }
    }
    function installCollectionsShim() {
        var primFunction = {
            uncurryThis: Function.prototype.bind.bind(Function.prototype.call)
        };
        var primObject = {
            getOwnPropertyNames: Object.getOwnPropertyNames.bind(Object),
            keys: Object.keys.bind(Object),
            seal: Object.seal.bind(Object),
            freeze: Object.freeze.bind(Object),
            preventExtensions: Object.preventExtensions.bind(Object),
            isExtensible: Object.isExtensible.bind(Object),
            hasOwn: primFunction.uncurryThis(Object.prototype.hasOwnProperty)
        };
        var primArray = {
            filter: primFunction.uncurryThis(Array.prototype.filter)
        };
        var primReflect = typeof Reflect === "undefined" ? undefined : {
            ownKeys: Reflect.ownKeys.bind(Reflect),
            preventExtensions: Reflect.preventExtensions.bind(Reflect),
            isExtensible: Reflect.isExtensible.bind(Reflect)
        };
        var INTERNAL_NS = [0x96, 0x89, 0x6a, 0xf3, 0xaf, 0xd9, 0x4e, 0xcc, 0xad, 0x7e, 0x53, 0x89, 0xd6, 0xe8, 0x21, 0x71];
        var WEAK_TABLE = uuid("[[WeakTable]]", INTERNAL_NS);
        var OBJECT_ID = uuid("[[ObjectId]]", INTERNAL_NS);
        Object.getOwnPropertyNames = function (o) {
            return primArray.filter(primObject.getOwnPropertyNames(o), isVisibleKey);
        };
        Object.keys = function (o) {
            return primArray.filter(primObject.keys(o), isVisibleKey);
        };
        Object.freeze = function (o) {
            if (primObject.isExtensible(o) && typeof o === "object" && o !== null)
                getOrCreateWeakTable(o, /*create*/ true);
            return primObject.freeze(o);
        };
        Object.seal = function (o) {
            if (primObject.isExtensible(o) && typeof o === "object" && o !== null)
                getOrCreateWeakTable(o, /*create*/ true);
            return primObject.seal(o);
        };
        Object.preventExtensions = function (o) {
            if (primObject.isExtensible(o) && typeof o === "object" && o !== null)
                getOrCreateWeakTable(o, /*create*/ true);
            return primObject.preventExtensions(o);
        };
        if (primReflect) {
            Reflect.ownKeys = function (o) {
                return primArray.filter(primReflect.ownKeys(o), isVisibleKey);
            };
            Reflect.preventExtensions = function (o) {
                if (primReflect.isExtensible(o) && typeof o === "object" && o !== null)
                    getOrCreateWeakTable(o, true);
                return primReflect.preventExtensions(o);
            };
        }
        function isVisibleKey(key) {
            return key !== WEAK_TABLE;
        }
        function getOrCreateWeakTable(target, create) {
            if (typeof target !== "object" || target === null)
                throw new TypeError();
            if (!primObject.hasOwn(target, WEAK_TABLE)) {
                if (!create) {
                    return undefined;
                }
                Object.defineProperty(target, WEAK_TABLE, { value: createHashMap() });
            }
            return target[WEAK_TABLE];
        }
        function hasWeakValue(target, key) {
            var weakTable = getOrCreateWeakTable(target, false);
            return weakTable !== undefined && key in weakTable;
        }
        function getWeakValue(target, key) {
            var weakTable = getOrCreateWeakTable(target, false);
            return weakTable && weakTable[key];
        }
        function setWeakValue(target, key, value) {
            return getOrCreateWeakTable(target, true)[key] = value;
        }
        function deleteWeakValue(target, key) {
            var weakTable = getOrCreateWeakTable(target, false);
            if (weakTable !== undefined && key in weakTable) {
                delete weakTable[key];
                return true;
            }
            return false;
        }
        function getId(target, keys, cacheSymbols) {
            if (target === null)
                return "null";
            if (typeof target === "undefined")
                return "undefined";
            if (typeof target === "number")
                return 1 / target === -Infinity ? "-0" : String(target);
            if (typeof target === "symbol")
                return "Symbol(" + (target in keys ? keys[target] : !cacheSymbols ? "" : keys[target] = uuid()) + ")";
            if (typeof target === "object" || typeof target === "function")
                return getWeakValue(target, OBJECT_ID) || setWeakValue(target, OBJECT_ID, uuid());
            if (typeof target === "boolean")
                return target ? "true" : "false";
            if (typeof target === "string")
                return JSON.stringify(target);
            return typeof target + "(" + target + ")";
        }
        // This needs to be loaded *after* the Symbol shim is installed
        var _a = require("collection-core"), KeyedCollection = _a.KeyedCollection, Collection = _a.Collection;
        var Map = /** @class */ (function () {
            function Map(entries) {
                var e_2, _a;
                this._keys = createHashMap();
                this._values = createHashMap();
                this._size = 0;
                if (entries !== undefined && entries !== null) {
                    try {
                        for (var entries_1 = tslib_1.__values(entries), entries_1_1 = entries_1.next(); !entries_1_1.done; entries_1_1 = entries_1.next()) {
                            var _b = tslib_1.__read(entries_1_1.value, 2), key = _b[0], value = _b[1];
                            this.set(key, value);
                        }
                    }
                    catch (e_2_1) { e_2 = { error: e_2_1 }; }
                    finally {
                        try {
                            if (entries_1_1 && !entries_1_1.done && (_a = entries_1.return)) _a.call(entries_1);
                        }
                        finally { if (e_2) throw e_2.error; }
                    }
                }
            }
            Object.defineProperty(Map.prototype, "size", {
                get: function () {
                    return this._size;
                },
                enumerable: true,
                configurable: true
            });
            Map.prototype.has = function (key) {
                var id = getId(key, this._keys, /*cacheSymbols*/ false);
                return id in this._keys;
            };
            Map.prototype.get = function (key) {
                var id = getId(key, this._keys, /*cacheSymbols*/ false);
                return id in this._keys ? this._values[id] : undefined;
            };
            Map.prototype.set = function (key, value) {
                var id = getId(key, this._keys, /*cacheSymbols*/ true);
                if (id in this._keys) {
                    this._values[id] = value;
                }
                else {
                    this._keys[id] = key;
                    this._values[id] = value;
                    this._size++;
                }
                return this;
            };
            Map.prototype.delete = function (key) {
                var id = getId(key, this._keys, /*cacheSymbols*/ false);
                if (id in this._keys) {
                    delete this._keys[id];
                    delete this._values[id];
                    if (typeof key === "symbol")
                        delete this._keys[key];
                    this._size--;
                    return true;
                }
                return false;
            };
            Map.prototype.clear = function () {
                this._keys = createHashMap();
                this._values = createHashMap();
                this._size = 0;
            };
            Map.prototype.keys = function () {
                return new KeyValueIterator(this._keys, this._values, "key");
            };
            Map.prototype.values = function () {
                return new KeyValueIterator(this._keys, this._values, "value");
            };
            Map.prototype.entries = function () {
                return new KeyValueIterator(this._keys, this._values, "key+value");
            };
            Map.prototype.forEach = function (cb, thisArg) {
                for (var id in this._keys) {
                    var key = this._keys[id];
                    var value = this._values[id];
                    cb.call(thisArg, value, key, this);
                }
            };
            Object.defineProperty(Map.prototype, KeyedCollection.size, {
                get: function () { return this.size; },
                enumerable: true,
                configurable: true
            });
            Map.prototype[KeyedCollection.has] = function (key) { return this.has(key); };
            Map.prototype[KeyedCollection.get] = function (key) { return this.get(key); };
            Map.prototype[KeyedCollection.set] = function (key, value) { this.set(key, value); };
            Map.prototype[KeyedCollection.delete] = function (key) { return this.delete(key); };
            Map.prototype[KeyedCollection.clear] = function () { this.clear(); };
            Map.prototype[KeyedCollection.keys] = function () { return this.keys(); };
            Map.prototype[KeyedCollection.values] = function () { return this.values(); };
            return Map;
        }());
        Object.defineProperty(Map.prototype, Symbol.toStringTag, { configurable: true, value: "Map" });
        Object.defineProperty(Map.prototype, Symbol.iterator, { configurable: true, writable: true, value: Map.prototype.entries });
        Object.defineProperty(Map, Symbol.species, { configurable: true, get: function () { return this; } });
        var Set = /** @class */ (function () {
            function Set(iterable) {
                var e_3, _a;
                this._values = createHashMap();
                this._size = 0;
                if (iterable !== undefined && iterable !== null) {
                    try {
                        for (var iterable_1 = tslib_1.__values(iterable), iterable_1_1 = iterable_1.next(); !iterable_1_1.done; iterable_1_1 = iterable_1.next()) {
                            var value = iterable_1_1.value;
                            this.add(value);
                        }
                    }
                    catch (e_3_1) { e_3 = { error: e_3_1 }; }
                    finally {
                        try {
                            if (iterable_1_1 && !iterable_1_1.done && (_a = iterable_1.return)) _a.call(iterable_1);
                        }
                        finally { if (e_3) throw e_3.error; }
                    }
                }
            }
            Object.defineProperty(Set.prototype, "size", {
                get: function () {
                    return this._size;
                },
                enumerable: true,
                configurable: true
            });
            Set.prototype.has = function (value) {
                var id = getId(value, this._values, /*cacheSymbols*/ false);
                return id in this._values;
            };
            Set.prototype.add = function (value) {
                var id = getId(value, this._values, /*cacheSymbols*/ true);
                if (id in this._values) {
                    return this;
                }
                else {
                    this._values[id] = value;
                    this._size++;
                }
                return this;
            };
            Set.prototype.delete = function (value) {
                var id = getId(value, this._values, /*cacheSymbols*/ false);
                if (id in this._values) {
                    delete this._values[id];
                    if (typeof value === "symbol")
                        delete this._values[value];
                    this._size--;
                    return true;
                }
                return false;
            };
            Set.prototype.clear = function () {
                this._values = createHashMap();
                this._size = 0;
            };
            Set.prototype.keys = function () {
                return new KeyValueIterator(this._values, this._values, "key");
            };
            Set.prototype.values = function () {
                return new KeyValueIterator(this._values, this._values, "value");
            };
            Set.prototype.entries = function () {
                return new KeyValueIterator(this._values, this._values, "key+value");
            };
            Set.prototype.forEach = function (cb, thisArg) {
                for (var id in this._values) {
                    var value = this._values[id];
                    cb.call(thisArg, value, value, this);
                }
            };
            Object.defineProperty(Set.prototype, Collection.size, {
                get: function () { return this.size; },
                enumerable: true,
                configurable: true
            });
            Set.prototype[Collection.has] = function (value) { return this.has(value); };
            Set.prototype[Collection.add] = function (value) { this.add(value); };
            Set.prototype[Collection.delete] = function (value) { return this.delete(value); };
            Set.prototype[Collection.clear] = function () { this.clear(); };
            return Set;
        }());
        Object.defineProperty(Set.prototype, Symbol.toStringTag, { configurable: true, value: "Set" });
        Object.defineProperty(Set.prototype, Symbol.iterator, { configurable: true, writable: true, value: Set.prototype.values });
        Object.defineProperty(Set, Symbol.species, { configurable: true, get: function () { return this; } });
        var WeakMap = /** @class */ (function () {
            function WeakMap() {
                this._key = uuid();
            }
            WeakMap.prototype.has = function (target) {
                return hasWeakValue(target, this._key);
            };
            WeakMap.prototype.get = function (target) {
                return getWeakValue(target, this._key);
            };
            WeakMap.prototype.set = function (target, value) {
                setWeakValue(target, this._key, value);
                return this;
            };
            WeakMap.prototype.delete = function (target) {
                return deleteWeakValue(target, this._key);
            };
            return WeakMap;
        }());
        Object.defineProperty(WeakMap.prototype, Symbol.toStringTag, { configurable: true, value: "WeakMap" });
        var WeakSet = /** @class */ (function () {
            function WeakSet() {
                this._key = uuid();
            }
            WeakSet.prototype.has = function (target) {
                return hasWeakValue(target, this._key);
            };
            WeakSet.prototype.add = function (target) {
                setWeakValue(target, this._key, true);
                return this;
            };
            WeakSet.prototype.delete = function (target) {
                return deleteWeakValue(target, this._key);
            };
            return WeakSet;
        }());
        Object.defineProperty(WeakSet.prototype, Symbol.toStringTag, { configurable: true, value: "WeakSet" });
        var KeyValueIterator = /** @class */ (function () {
            function KeyValueIterator(keys, values, kind) {
                this._keys = keys;
                this._values = values;
                this._kind = kind;
                var ids = [];
                for (var key in keys)
                    ids.push(key);
                this._ids = ids;
            }
            KeyValueIterator.prototype[Symbol.iterator] = function () { return this; };
            KeyValueIterator.prototype.next = function () {
                if (this._ids !== undefined) {
                    var id = void 0;
                    while ((id = this._ids.shift()) !== undefined) {
                        if (id in this._keys) {
                            switch (this._kind) {
                                case "key":
                                    return { value: this._keys[id], done: false };
                                case "value":
                                    return { value: this._values[id], done: false };
                                case "key+value":
                                    return { value: [this._keys[id], this._values[id]], done: false };
                            }
                        }
                    }
                    this._ids = undefined;
                    this._keys = undefined;
                    this._values = undefined;
                }
                return { value: undefined, done: true };
            };
            return KeyValueIterator;
        }());
        global.Map = Map;
        global.Set = Set;
        global.WeakMap = WeakMap;
        global.WeakSet = WeakSet;
        function createHashMap() {
            var hashMap = Object.create(null);
            hashMap["__"] = undefined;
            delete hashMap["__"];
            return hashMap;
        }
    }
}
//# sourceMappingURL=es2015.js.map