const t = require("debounceify"),
s = require("safety-catch")
function e(t, s) {
const e = t[s],
n = t.pop()
n !== e && ((t[s] = n), (n.index = s))
}
module.exports = class {
constructor(s, e) {
;((this.db = s),
(this.collection = e),
(this._listeners = []),
(this.onchange = t(this._onchange.bind(this))),
(this.watching = !1))
}
add(t, s = null) {
const e = new Promise((e, n) => {
const i = { target: t, condition: s, resolve: e, reject: n, index: -1 }
i.index = this._listeners.push(i) - 1
})
return (this._watch(), e)
}
_watch() {
;(this.onchange().catch(s), this.watching || this.db.watch(this.onchange), (this.watching = !0))
}
_unwatch() {
;(this.watching && this.db.unwatch(this.onchange), (this.watching = !1))
}
async _onchange() {
const t = this.db.snapshot()
try {
const s = []
for (const { target: e } of this._listeners) s.push(t.get(this.collection, e))
const e = await Promise.all(s)
for (let t = 0; t < this._listeners.length; t++) {
if (!e[t]) continue
const { condition: s } = this._listeners[t]
;(s && !s(e[t])) || this._settle(null, e[t], t)
}
} catch (t) {
this.destroy(t)
} finally {
t.close()
}
}
destroy(t) {
this._unwatch()
for (let s = 0; s < this._listeners.length; s++) this._settle(t, null, s)
}
_settle(t, s, n) {
const { resolve: i, reject: h } = this._listeners[n]
;(e(this._listeners, n), t ? h(t) : i(s))
}
}