import { build_view } from "./build_views";
class AbstractViewQuery {
    static __name__ = "AbstractViewQuery";
    *all_views() {
        yield* this.query(() => true);
    }
    *query(fn) {
        const visited = new Set();
        function* descend(view) {
            if (visited.has(view)) {
                return;
            }
            visited.add(view);
            if (fn(view)) {
                yield view;
            }
            for (const child of view.children()) {
                yield* descend(child);
            }
        }
        for (const view of this) {
            yield* descend(view);
        }
    }
    query_one(fn) {
        for (const view of this.query(fn)) {
            return view;
        }
        return null;
    }
    *find(model) {
        yield* this.query((view) => view.model == model);
    }
    *find_by_id(id) {
        yield* this.query((view) => view.model.id == id);
    }
    find_one(model) {
        for (const view of this.find(model)) {
            return view;
        }
        return null;
    }
    find_one_by_id(id) {
        for (const view of this.find_by_id(id)) {
            return view;
        }
        return null;
    }
    get_one(model) {
        const view = this.find_one(model);
        if (view != null) {
            return view;
        }
        else {
            throw new Error(`cannot find a view for ${model}`);
        }
    }
    get_one_by_id(id) {
        const view = this.find_one_by_id(id);
        if (view != null) {
            return view;
        }
        else {
            throw new Error(`cannot find a view for a model with '${id}' identity`);
        }
    }
    find_all(model) {
        return [...this.find(model)];
    }
    find_all_by_id(id) {
        return [...this.find_by_id(id)];
    }
}
export class ViewQuery extends AbstractViewQuery {
    view;
    static __name__ = "ViewQuery";
    constructor(view) {
        super();
        this.view = view;
    }
    *[Symbol.iterator]() {
        yield this.view;
    }
    toString() {
        return `ViewQuery(${this.view})`;
    }
}
export class ViewManager extends AbstractViewQuery {
    global;
    static __name__ = "ViewManager";
    _roots;
    constructor(roots = [], global) {
        super();
        this.global = global;
        this._roots = new Set(roots);
    }
    toString() {
        const views = [...this._roots].map((view) => `${view}`).join(", ");
        return `ViewManager(${views})`;
    }
    async build_view(model, parent = null) {
        const view = await build_view(model, { owner: this, parent });
        if (parent == null) {
            this.add(view);
        }
        return view;
    }
    get(model) {
        for (const view of this._roots) {
            if (view.model == model) {
                return view;
            }
        }
        return null;
    }
    get_by_id(id) {
        for (const view of this._roots) {
            if (view.model.id == id) {
                return view;
            }
        }
        return null;
    }
    add(view) {
        this._roots.add(view);
        this.global?.add(view);
    }
    delete(view) {
        this._roots.delete(view);
        this.global?.delete(view);
    }
    remove(view) {
        this.delete(view);
    }
    clear() {
        for (const view of this) {
            view.remove();
        }
    }
    /* TODO (TS 5.2)
    [Symbol.dispose](): void {
      this.clear()
    }
    */
    get roots() {
        return [...this._roots];
    }
    *[Symbol.iterator]() {
        yield* this._roots;
    }
}
//# sourceMappingURL=view_manager.js.map