import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import { CuckooFilter, optimize } from './cuckoo-filter.js';
import { fnv1a } from './hashes.js';
import { getRandomInt } from './utils.js';
export class ScalableCuckooFilter {
    filterSize;
    bucketSize;
    fingerprintSize;
    scale;
    filterSeries;
    hash;
    seed;
    constructor(init) {
        this.bucketSize = init.bucketSize ?? 4;
        this.filterSize = init.filterSize ?? (1 << 18) / this.bucketSize;
        this.fingerprintSize = init.fingerprintSize ?? 2;
        this.scale = init.scale ?? 2;
        this.hash = init.hash ?? fnv1a;
        this.seed = init.seed ?? getRandomInt(0, Math.pow(2, 10));
        this.filterSeries = [
            new CuckooFilter({
                filterSize: this.filterSize,
                bucketSize: this.bucketSize,
                fingerprintSize: this.fingerprintSize,
                hash: this.hash,
                seed: this.seed
            })
        ];
    }
    add(item) {
        if (typeof item === 'string') {
            item = uint8ArrayFromString(item);
        }
        if (this.has(item)) {
            return true;
        }
        let current = this.filterSeries.find((cuckoo) => {
            return cuckoo.reliable;
        });
        if (current == null) {
            const curSize = this.filterSize * Math.pow(this.scale, this.filterSeries.length);
            current = new CuckooFilter({
                filterSize: curSize,
                bucketSize: this.bucketSize,
                fingerprintSize: this.fingerprintSize,
                hash: this.hash,
                seed: this.seed
            });
            this.filterSeries.push(current);
        }
        return current.add(item);
    }
    has(item) {
        if (typeof item === 'string') {
            item = uint8ArrayFromString(item);
        }
        for (let i = 0; i < this.filterSeries.length; i++) {
            if (this.filterSeries[i].has(item)) {
                return true;
            }
        }
        return false;
    }
    remove(item) {
        if (typeof item === 'string') {
            item = uint8ArrayFromString(item);
        }
        for (let i = 0; i < this.filterSeries.length; i++) {
            if (this.filterSeries[i].remove(item)) {
                return true;
            }
        }
        return false;
    }
    get count() {
        return this.filterSeries.reduce((acc, curr) => {
            return acc + curr.count;
        }, 0);
    }
}
export function createScalableCuckooFilter(maxItems, errorRate = 0.001, options) {
    return new ScalableCuckooFilter({
        ...optimize(maxItems, errorRate),
        ...(options ?? {})
    });
}
//# sourceMappingURL=scalable-cuckoo-filter.js.map