const e = require("safety-catch"),
s = require("hypercore-id-encoding"),
t = require("b4a"),
{ EventEmitter: i } = require("events"),
{ createResourceManager: n } = require("../lib/common"),
a = require("./media"),
o = require("./presence"),
r = 225,
c = 256
class l {
constructor(e) {
;((this.connection = e),
(this.closed = !1),
(this.localAlias = 0),
(this._proxiesByRemoteAlias = new Array(c)),
(this._prefixesByLocalAlias = new Array(c)),
(this._onmessage = this._onMessage.bind(this)),
this.connection.rawStream.on("message", this._onmessage))
}
_onMessage(e) {
if (this.closed) return
const s = e[0],
t = this._proxiesByRemoteAlias[s]
t && t.handleRawStreamData(e.subarray(2))
}
createLocalAlias() {
this.localAlias = (this.localAlias + 1) % c
const e = t.allocUnsafe(2)
return (
(e[0] = this.localAlias),
(e[1] = r),
(this._prefixesByLocalAlias[this.localAlias] = e),
this.localAlias
)
}
send(e, s) {
if (this.closed) return
const i = t.allocUnsafe(s.byteLength + 2)
;(this._prefixesByLocalAlias[e].copy(i, 0), s.copy(i, 2), this.connection.rawStream.trySend(i))
}
registerProxy(e, s) {
this._proxiesByRemoteAlias[e] = s
}
unregisterProxy(e) {
this._proxiesByRemoteAlias[e] = null
}
close() {
;((this.closed = !0), this.connection.rawStream.removeListener("message", this._onmessage))
}
}
module.exports = class extends i {
constructor(s, { firewall: t, onerror: i = e, skipJoinLeave: r = !1 } = {}) {
;(super(),
(this.swarm = s),
(this.onerror = i),
(this.firewall = t),
(this._localAlias = 0),
(this._rawMuxersByStream = new Map()))
const {
collection: c,
asyncMethod: l,
subscription: h,
} = n((e) => new a(this, e), this._updateCall.bind(this)),
{ collection: d, asyncMethod: _, subscription: u } = n((e) => new o(this, e, t))
;((this._mediaByCallId = c),
(this._presenceByCallId = d),
(this._connectionsBySwarmId = new Map()),
(this._activatedCalls = new Set()),
(this.activateCall = this._activateCall.bind(this)),
(this.deactivateCall = this._deactivateCall.bind(this)),
(this._skipJoinLeave = !0 === r),
(this.authorize = this._authorize.bind(this)),
(this.deauthorize = this._deauthorize.bind(this)),
(this.joinPeer = this._joinPeer.bind(this)),
(this.leavePeer = this._leavePeer.bind(this)),
(this.signalMedia = l(this._signalMedia.bind(this))),
(this.subscribeMediaSignals = h(this._subscribeMediaSignals.bind(this))),
(this.subscribeProxyUpdates = h(this._subscribeProxyUpdates.bind(this))),
(this.setPresent = _(this._setPresent.bind(this))),
(this.setNotPresent = _(this._setNotPresent.bind(this))),
(this.subscribePresence = u(this._subscribePresence.bind(this))),
(this.getPresence = _(this._getPresence.bind(this))))
const v = this
;((this._onconnection = this._onConnection.bind(this)),
(this._onconnectionclosed = function () {
v._onConnectionClosed(this)
}),
this.swarm.on("connection", this._onconnection))
}
setSkipJoinLeave(e) {
this._skipJoinLeave !== e && (this._skipJoinLeave = e)
}
get callIsActive() {
return this._mediaByCallId.size > 0
}
_updateCall(e, s) {
1 === this._mediaByCallId.size && s
? this.emit("call-active", e)
: 0 !== this._mediaByCallId.size || s || this.emit("call-inactive", e)
}
mediaIsActive(e) {
return this._mediaByCallId.has(e)
}
shouldActivate(e) {
return this.mediaIsActive(e) || this._activatedCalls.has(e)
}
_activateCall(e) {
this._activatedCalls.add(e)
const s = this._presenceByCallId.get(e)
s && s.value.activate()
}
_deactivateCall(e) {
this._activatedCalls.delete(e)
const s = this._presenceByCallId.get(e)
s && s.value.deactivate()
}
internalActivateCall(e) {
return this._activateCall(e.callId)
}
internalDeactivateCall(e) {
return this._deactivateCall(e.callId)
}
close() {
this.swarm.removeListener("connection", this._onconnection)
for (const e of this.swarm.connections) e.removeListener("close", this._onconnectionclosed)
for (const e of this._rawMuxersByStream.values()) e.close()
for (const { value: e } of this._mediaByCallId.values()) e.close()
for (const { value: e } of this._presenceByCallId.values()) e.close()
}
_onConnection(e) {
const t = s.encode(e.remotePublicKey),
i = this._connectionsBySwarmId.get(t)
;(i && i !== e && this._onConnectionClosed(i), this._connectionsBySwarmId.set(t, e))
const n = new l(e)
;(this._rawMuxersByStream.set(e, n), e.on("close", this._onconnectionclosed))
for (const { value: s } of this._mediaByCallId.values()) s.addConnection(e, n)
for (const { value: s } of this._presenceByCallId.values()) s.addConnection(e)
}
_onConnectionClosed(e) {
const t = s.encode(e.remotePublicKey)
this._connectionsBySwarmId.get(t) === e && this._connectionsBySwarmId.delete(t)
const i = this._rawMuxersByStream.get(e)
i && (i.close(), this._rawMuxersByStream.delete(e))
for (const { value: s } of this._mediaByCallId.values()) s.removeConnection(e, i)
for (const { value: s } of this._presenceByCallId.values()) s.removeConnection(e)
}
_authorize(e, s) {}
_deauthorize(e, s) {}
_joinPeer(e) {
if (!this._skipJoinLeave) return this.swarm.joinPeer(s.decode(e))
}
_leavePeer(e) {
if (!this._skipJoinLeave) return this.swarm.leavePeer(s.decode(e))
}
_signalMedia(e, s, t) {
const i = this._connectionsBySwarmId.get(s)
return e.signal(i, t)
}
_subscribeMediaSignals(e) {
return e.subscribeMediaSignals()
}
_subscribeProxyUpdates(e) {
return e.subscribeProxyUpdates()
}
_subscribePresence(e) {
return e.subscribePresence()
}
_getPresence(e) {
return e.getPresence()
}
_setPresent(e, s) {
return e.setPresence(s)
}
_setNotPresent(e) {
return e.setNotPresent()
}
debugSetHaveFilter(e) {
this._haveFilter = e
for (const { tracker: e } of this._trackersByCallId.values())
e.debugSetHaveFilter(this._haveFilter)
}
}