"use strict";
// SPDX-FileCopyrightText: 2025 Gnuxie <Gnuxie@protonmail.com>
//
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.StandardRoomTakedown = void 0;
const matrix_protection_suite_1 = require("matrix-protection-suite");
const typescript_result_1 = require("@gnuxie/typescript-result");
const log = new matrix_protection_suite_1.Logger("RoomTakedown");
/**
 * This exists as the main handler for reacting to literal room policies
 * (that have been reversed from hashed policies elsewhere) AND
 * moving discovered rooms into the hashStore. Although it's not clear
 * whether we need to do that?
 */
class StandardRoomTakedown {
    auditLog;
    takedownCapability;
    constructor(auditLog, takedownCapability) {
        this.auditLog = auditLog;
        this.takedownCapability = takedownCapability;
        // nothing to do
    }
    async takedownRoom(roomID, rule) {
        const isRoomTakendownResult = await this.takedownCapability.isRoomTakendown(roomID);
        if ((0, typescript_result_1.isError)(isRoomTakendownResult)) {
            return isRoomTakendownResult;
        }
        if (isRoomTakendownResult.ok) {
            log.debug(`The room ${roomID} has already been taken down according to your homeserver`);
            return (0, typescript_result_1.Ok)(undefined);
        }
        const detailsResult = await this.takedownCapability.getRoomDetails(roomID);
        const takedownResult = await this.takedownCapability.takedownRoom(roomID);
        if ((0, typescript_result_1.isError)(takedownResult)) {
            return takedownResult;
        }
        // Only audit the takedown if the capability is not simulated.
        if (this.takedownCapability.isSimulated) {
            return (0, typescript_result_1.Ok)(undefined);
        }
        const details = (() => {
            if ((0, typescript_result_1.isError)(detailsResult)) {
                log.error("Unable to fetch details for room before takedown", roomID, detailsResult.error);
                return { room_id: roomID };
            }
            else {
                return detailsResult.ok;
            }
        })();
        return await this.auditLog.takedownRoom(rule, details);
    }
    // FIXME: I'm really unhappy with the length of these method bodies
    // and also the slight duplication in regards to figuring out whether
    // particular policies apply to rooms or not.
    async handlePolicyChange(revision, changes) {
        const roomsToTakedown = new Map();
        for (const change of changes) {
            if (change.rule.matchType !== matrix_protection_suite_1.PolicyRuleMatchType.Literal ||
                change.changeType === matrix_protection_suite_1.PolicyRuleChangeType.Removed) {
                continue; // We only care about literal policies
            }
            if (change.rule.kind === matrix_protection_suite_1.PolicyRuleType.Room &&
                change.rule.recommendation === matrix_protection_suite_1.Recommendation.Takedown) {
                roomsToTakedown.set(change.rule.entity, change.rule);
            }
        }
        for (const [roomID, policy] of roomsToTakedown.entries()) {
            const takedownResult = await this.takedownRoom(roomID, policy);
            if ((0, typescript_result_1.isError)(takedownResult)) {
                log.error("Error while trying to takedown the room:", policy.entity, takedownResult.error);
            }
        }
        return (0, typescript_result_1.Ok)(undefined);
    }
    async checkAllRooms(revision) {
        log.debug("Checking all rooms for policies");
        // We want all takedowns.
        const roomPolicies = revision
            .allRulesOfType(matrix_protection_suite_1.PolicyRuleType.Room, matrix_protection_suite_1.Recommendation.Takedown)
            .filter((policy) => policy.matchType === matrix_protection_suite_1.PolicyRuleMatchType.Literal);
        const roomsToCheck = new Map();
        for (const policy of roomPolicies) {
            roomsToCheck.set(policy.entity, policy);
        }
        for (const [roomID, policy] of roomsToCheck.entries()) {
            if (this.auditLog.isRoomTakendown(roomID)) {
                continue; // room already takendown
            }
            const takedownResult = await this.takedownRoom(roomID, policy);
            if ((0, typescript_result_1.isError)(takedownResult)) {
                log.error("Error while trying to takedown the room:", policy.entity, takedownResult.error);
            }
        }
        log.debug("Finished checking all rooms for policies");
        return (0, typescript_result_1.Ok)(undefined);
    }
}
exports.StandardRoomTakedown = StandardRoomTakedown;
//# sourceMappingURL=RoomTakedown.js.map