/**
 * @copyright Sister Software
 * @license AGPL-3.0
 * @author Teffen Ellis, et al.
 */
/**
 * Index mapping a specific value to originating languages.
 *
 * If a value is present in this index, it means that the value is a valid value in at least one
 * language.
 */
export class LocaleIndex extends Map {
    /**
     * The normalizer to use for placenames.
     */
    normalizer;
    /**
     * The source of the index.
     */
    displayName;
    constructor(entries = [], options) {
        super();
        this.displayName = options?.displayName ?? "unknown";
        this.normalizer = options?.normalizer;
        for (const [placename, languageCodes] of entries) {
            this.add(placename, ...languageCodes);
        }
    }
    /**
     * Add a placename to the index, associating it with the given language codes.
     *
     * @param placename The placename to add.
     * @param languageCodes The language codes to associate with the placename.
     */
    add(placename, ...languageCodes) {
        if (languageCodes.length === 0) {
            throw new Error(`At least one language code must be provided for "${placename}".`);
        }
        if (this.normalizer) {
            placename = this.normalizer.normalize(placename);
            if (!this.normalizer.validate(placename))
                return;
        }
        if (!placename)
            return;
        const placenameIndex = this.open(placename);
        placenameIndex.displayName = this.displayName;
        for (const language of languageCodes) {
            placenameIndex.add(language);
        }
    }
    /**
     * Remove a placename from the index.
     *
     * @param placename The placename to remove.
     */
    remove(placename) {
        if (this.normalizer) {
            placename = this.normalizer.normalize(placename);
        }
        if (!placename)
            return;
        super.delete(placename);
    }
    open(placename) {
        if (this.normalizer) {
            placename = this.normalizer.normalize(placename);
        }
        if (!placename) {
            throw new Error(`Placename "${placename}" is empty or invalid.`);
        }
        let placenameIndex = this.get(placename);
        if (!placenameIndex) {
            placenameIndex = new Set();
            this.set(placename, placenameIndex);
        }
        return placenameIndex;
    }
    /**
     * Serialize the index to JSON.
     */
    toJSON() {
        const entries = [];
        for (const [placename, languages] of this) {
            entries.push([placename, Array.from(languages)]);
        }
        return entries;
    }
}
//# sourceMappingURL=LocaleIndex.js.map