"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Space = void 0;
const MatrixEntity_1 = require("../helpers/MatrixEntity");
const simple_validation_1 = require("../simple-validation");
const SpaceChildEvent_1 = require("./events/SpaceChildEvent");
/**
 * An instance representing a Matrix Space. A space is tied to a room.
 * @category Models
 */
class Space {
    constructor(roomId, client) {
        this.roomId = roomId;
        this.client = client;
    }
    /**
     * Creates a new child space under this space.
     * @param {SpaceCreateOptions} opts The options for the new space.
     * @returns {Promise<Space>} Resolves to the created space.
     */
    createChildSpace(opts) {
        return __awaiter(this, void 0, void 0, function* () {
            const space = yield this.client.createSpace(opts);
            yield this.addChildSpace(space, opts);
            return space;
        });
    }
    /**
     * Adds a child space to the space. Must be joined to both spaces.
     * @param {Space} space The space to add.
     * @param {SpaceChildEntityOptions} childOpts Related options for the child's representation.
     * @returns {Promise<Space>} Resolves when complete.
     */
    addChildSpace(space, childOpts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.addChildRoom(space.roomId, childOpts);
        });
    }
    /**
     * Removes a child space from the space. Must be joined to the current space (not needed for child space).
     * @param {Space} space The space to remove.
     * @returns {Promise<void>} Resolves when complete.
     */
    removeChildSpace(space) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.removeChildRoom(space.roomId);
        });
    }
    /**
     * Adds a child room to the space. Must be joined to both the room and the space.
     * @param {string} roomId The room ID to add.
     * @param {SpaceChildEntityOptions} childOpts Additional options for the child space.
     * @returns {Promise<void>} Resolves when complete.
     */
    addChildRoom(roomId, childOpts = {}) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const via = (_a = childOpts.via) !== null && _a !== void 0 ? _a : [new MatrixEntity_1.UserID(yield this.client.getUserId()).domain];
            const childContent = { via };
            if (childOpts.suggested)
                childContent.suggested = childOpts.suggested;
            if (childOpts.order) {
                simple_validation_1.validateSpaceOrderString(childOpts.order);
                childContent.order = childOpts.order;
            }
            yield this.client.sendStateEvent(this.roomId, "m.space.child", roomId, childContent);
        });
    }
    /**
     * Removes a child room from the space. Must be joined to the current space (not needed for child room).
     * @param {string} roomId The room ID to remove.
     * @returns {Promise<void>} Resolves when complete.
     */
    removeChildRoom(roomId) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.client.sendStateEvent(this.roomId, "m.space.child", roomId, {});
        });
    }
    /**
     * Gets all the child rooms on the space. These may be spaces or other rooms.
     * @returns {Promise<SpaceEntityMap>} Resolves to a map of children for this space.
     */
    getChildEntities() {
        return __awaiter(this, void 0, void 0, function* () {
            const roomState = yield this.client.getRoomState(this.roomId);
            let mapping = {};
            roomState
                .filter(s => s.type === "m.space.child")
                .filter(s => { var _a; return (_a = s.content) === null || _a === void 0 ? void 0 : _a.via; })
                .forEach(s => mapping[s.state_key] = new SpaceChildEvent_1.SpaceChildEvent(s));
            return mapping;
        });
    }
    /**
     * Invite a user to the current space.
     * @param {string} userId The user ID to invite.
     * @returns {Promise<void>} Resolves when completed.
     */
    inviteUser(userId) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.client.inviteUser(userId, this.roomId);
        });
    }
}
exports.Space = Space;
