import { isElement } from '../util.js';
function mutationFilter(nodes, filter) {
    if (!filter) {
        return nodes;
    }
    return Array.isArray(filter)
        ? nodes.filter((node) => filter.some((selector) => isElement(node) && node.matches(selector)))
        : nodes.filter((node) => filter(node));
}
class MutationController {
    constructor(host, options) {
        this._host = host;
        this._callback = options.callback;
        this._config = options.config;
        this._target = options.target ?? this._host;
        this._filter = options.filter ?? [];
        this._observer = new MutationObserver((records) => {
            this.disconnect();
            this._callback.call(this._host, this._process(records));
            this.observe();
        });
        host.addController(this);
    }
    hostConnected() {
        this.observe();
    }
    hostDisconnected() {
        this.disconnect();
    }
    _process(records) {
        const changes = {
            attributes: [],
            added: [],
            removed: [],
        };
        const filter = this._filter;
        for (const record of records) {
            if (record.type === 'attributes') {
                changes.attributes.push(...mutationFilter([record.target], filter));
            }
            else if (record.type === 'childList') {
                changes.added.push(...mutationFilter(Array.from(record.addedNodes), filter).map((node) => ({ target: record.target, node })));
                changes.removed.push(...mutationFilter(Array.from(record.removedNodes), filter).map((node) => ({ target: record.target, node })));
            }
        }
        return { records, changes, observer: this };
    }
    observe() {
        this._observer.observe(this._target, this._config);
    }
    disconnect() {
        this._observer.disconnect();
    }
}
export function createMutationController(host, config) {
    return new MutationController(host, config);
}
//# sourceMappingURL=mutation-observer.js.map