"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutboundStream = void 0;
const ref_napi_1 = __importDefault(require("ref-napi"));
const events_1 = require("./events");
const impls_1 = require("./events/impls");
const native_1 = require("./native");
const Handler_OutboundStreamOnPeerChange_1 = require("./events/Handler_OutboundStreamOnPeerChange");
const Handler_OutboundStreamOnClose_1 = require("./events/Handler_OutboundStreamOnClose");
const Handler_OutboundStreamOnInput_1 = require("./events/Handler_OutboundStreamOnInput");
/**
 * An outbound stream from our device to another Peer on the Rainway Network.
 */
class OutboundStream extends events_1.EventEmitter {
    /** @internal */
    constructor(owner, id, type, processIds) {
        super();
        this.id = id;
        this.peer = owner;
        this.type = type;
        this.processIds = processIds !== null && processIds !== void 0 ? processIds : [];
        // peer join/leave handlers
        this._peerJoinHandler = new Handler_OutboundStreamOnPeerChange_1.Handler_OutboundStreamOnPeerChange((id) => {
            const peer = this.peer.connection.peers.find((p) => p.id === id);
            if (peer) {
                this.emit("peer-join", new impls_1.PeerJoinEvent(peer));
            }
        });
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_peer_join_handler", () => native_1.native.rainway_outbound_stream_set_peer_join_handler(this.id, this._peerJoinHandler.handler));
        this._peerLeaveHandler = new Handler_OutboundStreamOnPeerChange_1.Handler_OutboundStreamOnPeerChange((id) => {
            const peer = this.peer.connection.peers.find((p) => p.id === id);
            if (peer) {
                this.emit("peer-leave", new impls_1.PeerLeaveEvent(peer));
            }
        });
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_peer_leave_handler", () => native_1.native.rainway_outbound_stream_set_peer_leave_handler(this.id, this._peerLeaveHandler.handler));
        this._inputHandler = new Handler_OutboundStreamOnInput_1.Handler_OutboundStreamOnInput((ev) => {
            const event = new impls_1.InputEvent(ev);
            this.emit("input", event);
            return !event.defaultPrevented;
        });
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_input_filter", () => native_1.native.rainway_outbound_stream_set_input_filter(this.id, this._inputHandler.handler));
        this._closeHandler = new Handler_OutboundStreamOnClose_1.Handler_OutboundStreamOnClose(() => {
            this.emit("close", new impls_1.CloseEvent(new Error()));
        });
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_close_handler", () => native_1.native.rainway_outbound_stream_set_close_handler(this.id, this._closeHandler.handler));
    }
    /**
     * Gets or sets the default permissions granted to peers within this outbound stream.
     * See also {@link OutboundStream.getPeerPermission} which facilities modifying specific peer permissions, overriding this default.
     */
    get permissions() {
        const storage = Buffer.alloc(ref_napi_1.default.sizeof.int);
        storage.type = ref_napi_1.default.types.int;
        (0, native_1.invokeOrError)("rainway_outbound_stream_get_peer_default_permissions", () => native_1.native.rainway_outbound_stream_get_peer_default_permissions(this.id, storage.ref()));
        return storage.deref();
    }
    set permissions(value) {
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_peer_default_permissions", () => native_1.native.rainway_outbound_stream_set_peer_default_permissions(this.id, value));
    }
    /**
     * Retrieve the (optional) override permissions for a given peer.
     * This overrides {@link OutboundStream.permissions} for a specific peer.
     * If no override is present, the value of {@link OutboundStream.permissions} will be returned.
     * @param peer - peer or peer id
     * @returns permissions
     */
    getPeerPermission(peer) {
        const id = typeof peer === "bigint" ? peer : peer.id;
        const storage = Buffer.alloc(ref_napi_1.default.sizeof.int);
        storage.type = ref_napi_1.default.types.int;
        (0, native_1.invokeOrError)("rainway_outbound_stream_get_peer_permissions", () => native_1.native.rainway_outbound_stream_get_peer_permissions(this.id, id.toString(), storage));
        return storage.deref();
    }
    /**
     * Set the (optional) override permissions for a given peer.
     * This overrides {@link OutboundStream.permissions} for a specific peer.
     * @param peer - peer or peer id
     * @param value - permissions
     */
    setPeerPermission(peer, value) {
        const id = typeof peer === "bigint" ? peer : peer.id;
        (0, native_1.invokeOrError)("rainway_outbound_stream_set_peer_permissions", () => native_1.native.rainway_outbound_stream_set_peer_permissions(this.id, id.toString(), value));
    }
    /**
     * Destroys the peer connection, including all sub resources.
     */
    close() {
        (0, native_1.invokeOrError)("rainway_outbound_stream_close", () => native_1.native.rainway_outbound_stream_close(this.id));
        this.emit("close", new impls_1.CloseEvent(new Error()));
    }
}
exports.OutboundStream = OutboundStream;
//# sourceMappingURL=outbound-stream.js.map