"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BiDirectionalDeepMap = void 0;
const errors_1 = require("./errors");
const map_1 = require("./map");
const utils_1 = require("./utils");
/**
 * A DeepMap implementation that supports O(1) lookups by both keys and values
 * NOTE: All key-value pairs must be 1-to-1
 */
class BiDirectionalDeepMap extends map_1.DeepMap {
    /**
     * @param entries optional list of key-value pairs to initialize the map
     * @param options configuration options
     */
    constructor(entries, options) {
        super(entries, options);
        const valueEntries = entries ? entries.map(([key, val]) => [this.normalizeValue(val), key]) : null;
        this.valueMap = new Map(valueEntries);
    }
    /**
     * @inheritdoc
     */
    set(key, val) {
        // Enforce 1-to-1: Don't allow writing a value which is already present in the map for a different key
        const preexistingValueKey = this.getKeyByValue(val);
        if (preexistingValueKey !== undefined && this.normalizeKey(preexistingValueKey) !== this.normalizeKey(key)) {
            throw new errors_1.DeepEqualityDataStructuresError(`Could not set key='${(0, utils_1.stringify)(key)}': The value='${(0, utils_1.stringify)(val)}' is already associated with key='${(0, utils_1.stringify)(preexistingValueKey)}'`);
        }
        this.valueMap.set(this.normalizeValue(val), key);
        return super.set(key, val);
    }
    /**
     * @inheritdoc
     */
    delete(key) {
        const val = this.get(key);
        if (val) {
            this.valueMap.delete(this.normalizeValue(val));
        }
        return super.delete(key);
    }
    /**
     * @inheritdoc
     */
    clear() {
        this.valueMap.clear();
        super.clear();
    }
    // BI-DIRECTIONAL API
    /**
     * @returns true if the given value is present in the key-value map.
     */
    hasValue(val) {
        return this.valueMap.has(this.normalizeValue(val));
    }
    /**
     * @returns the key associated with the specified value
     */
    getKeyByValue(val) {
        return this.valueMap.get(this.normalizeValue(val));
    }
    /**
     * @returns true if a value in the map existed and has been removed, else false
     */
    deleteByValue(val) {
        const key = this.getKeyByValue(val);
        return key ? this.delete(key) : false;
    }
}
exports.BiDirectionalDeepMap = BiDirectionalDeepMap;
