var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import EventEmitter, { InvalidArgumentError, inspect, } from './utilities/EventEmitter.js';
import Leavers from './Leavers.js';
class Members extends EventEmitter {
    constructor(space) {
        super();
        this.space = space;
        this.lastMemberUpdate = {};
        this.leavers = new Leavers(this.space.options.offlineTimeout);
    }
    processPresenceMessage(message) {
        return __awaiter(this, void 0, void 0, function* () {
            const { action, connectionId } = message;
            const isLeaver = !!this.leavers.getByConnectionId(connectionId);
            const member = this.createMember(message);
            if (action === 'leave') {
                this.leavers.addLeaver(member, () => this.onMemberOffline(member));
                this.emit('leave', member);
                this.emit('update', member);
            }
            else if (isLeaver) {
                this.leavers.removeLeaver(connectionId);
            }
            if (action === 'enter') {
                this.emit('enter', member);
                this.emit('update', member);
            }
            // Emit profileData updates only if they are different then the last held update.
            // A locationUpdate is handled in Locations.
            if (message.data.profileUpdate.id && this.lastMemberUpdate[connectionId] !== message.data.profileUpdate.id) {
                this.lastMemberUpdate[message.connectionId] = message.data.profileUpdate.id;
                this.emit('updateProfile', member);
                this.emit('update', member);
            }
        });
    }
    getSelf() {
        return __awaiter(this, void 0, void 0, function* () {
            return this.space.connectionId ? yield this.getByConnectionId(this.space.connectionId) : null;
        });
    }
    getAll() {
        return __awaiter(this, void 0, void 0, function* () {
            const presenceMembers = yield this.space.channel.presence.get();
            const members = presenceMembers.map((m) => this.createMember(m));
            return members.concat(this.leavers.getAll().map((l) => l.member));
        });
    }
    getOthers() {
        return __awaiter(this, void 0, void 0, function* () {
            const members = yield this.getAll();
            return members.filter((m) => m.connectionId !== this.space.connectionId);
        });
    }
    subscribe(listenerOrEvents, listener) {
        try {
            super.on(listenerOrEvents, listener);
        }
        catch (e) {
            if (e instanceof InvalidArgumentError) {
                throw new InvalidArgumentError('Members.subscribe(): Invalid arguments: ' + inspect([listenerOrEvents, listener]));
            }
            else {
                throw e;
            }
        }
    }
    unsubscribe(listenerOrEvents, listener) {
        try {
            super.off(listenerOrEvents, listener);
        }
        catch (e) {
            if (e instanceof InvalidArgumentError) {
                throw new InvalidArgumentError('Members.unsubscribe(): Invalid arguments: ' + inspect([listenerOrEvents, listener]));
            }
            else {
                throw e;
            }
        }
    }
    getByConnectionId(connectionId) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const members = yield this.getAll();
            return (_a = members.find((m) => m.connectionId === connectionId)) !== null && _a !== void 0 ? _a : null;
        });
    }
    createMember(message) {
        return {
            clientId: message.clientId,
            connectionId: message.connectionId,
            isConnected: message.action !== 'leave',
            profileData: message.data.profileUpdate.current,
            location: message.data.locationUpdate.current,
            lastEvent: {
                name: message.action,
                timestamp: message.timestamp,
            },
        };
    }
    onMemberOffline(member) {
        return __awaiter(this, void 0, void 0, function* () {
            this.leavers.removeLeaver(member.connectionId);
            this.emit('remove', member);
            this.emit('update', member);
            if (member.location) {
                this.space.locations.emit('update', {
                    previousLocation: member.location,
                    currentLocation: null,
                    member: Object.assign(Object.assign({}, member), { location: null }),
                });
            }
            this.space.emit('update', { members: yield this.getAll() });
        });
    }
}
export default Members;
//# sourceMappingURL=Members.js.map