"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeepSet = void 0;
const map_1 = require("./map");
/**
 * A Set implementation that supports deep equality for values.
 */
class DeepSet extends Set {
    // NOTE: This is actually a thin wrapper. We're not using super other than to drive the (typed) API contract.
    /**
     * @param values optional list of values to initialize the set
     * @param options configuration options
     */
    constructor(values, options) {
        super();
        this.options = options;
        const transformedEntries = values ? values.map((el) => [el, null]) : null;
        this.map = new map_1.DeepMap(transformedEntries, options);
    }
    /**
     * Getter for number of elements in the set.
     * @inheritdoc
     */
    get size() {
        return this.map.size;
    }
    /**
     * Returns true if the given value is present in the set.
     * @inheritdoc
     */
    has(val) {
        return this.map.has(val);
    }
    /**
     * @inheritdoc
     */
    add(val) {
        this.map.set(val, null);
        return this;
    }
    /**
     * @inheritdoc
     */
    delete(val) {
        return this.map.delete(val);
    }
    /**
     * Clear all values from the map.
     * @inheritdoc
     */
    clear() {
        this.map.clear();
    }
    /**
     * @inheritdoc
     */
    forEach(callbackfn) {
        this.map.forEach((_mapVal, mapKey, _map) => {
            callbackfn(mapKey, mapKey, this);
        });
    }
    /**
     * @inheritdoc
     */
    *[Symbol.iterator]() {
        for (const [key, _val] of this.map[Symbol.iterator]()) {
            yield key;
        }
    }
    /**
     * @inheritdoc
     */
    *entries() {
        for (const val of this[Symbol.iterator]()) {
            yield [val, val];
        }
    }
    /**
     * @inheritdoc
     */
    *keys() {
        for (const val of this[Symbol.iterator]()) {
            yield val;
        }
    }
    /**
     * @inheritdoc
     */
    *values() {
        yield* this.keys();
    }
    /**
     * @param other the set to compare against
     * @returns true if the values of `other` are the same as this set
     */
    equals(other) {
        return this.map.equals(other['map']);
    }
    /**
     * @param other the set to compare against
     * @returns true if the values of `other` are all contained in this set
     */
    contains(other) {
        return this.map.contains(other['map']);
    }
    /**
     * @param other the set to compare against
     * @returns a new set whose values are the union of `this` and `other`.
     */
    union(other) {
        return this.getSetFromMapKeys(this.map.union(other['map']));
    }
    /**
     * @param other the set to compare against
     * @returns a new set containing all values in `this` that are also in `other`.
     */
    intersection(other) {
        return this.getSetFromMapKeys(this.map.intersection(other['map']));
    }
    /**
     * @param other the set to compare against
     * @returns a new set containing all values in `this` that are not also in `other`.
     */
    difference(other) {
        return this.getSetFromMapKeys(this.map.difference(other['map']));
    }
    getSetFromMapKeys(map) {
        return new DeepSet([...map.keys()], this.options);
    }
}
exports.DeepSet = DeepSet;
