"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.AppserviceJoinRoomStrategy = void 0;
/**
 * A join strategy for application services that proxies joins to an underlying join
 * strategy while also trying to use the appservice's bot user to invite the underlying
 * user if needed.
 * @category Join strategies
 */
class AppserviceJoinRoomStrategy {
    constructor(underlyingStrategy, appservice) {
        this.underlyingStrategy = underlyingStrategy;
        this.appservice = appservice;
    }
    joinRoom(roomIdOrAlias, userId, apiCall) {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                // First just try joining via the apiCall
                return yield apiCall(roomIdOrAlias);
            }
            catch (err) {
                // If the user being joined is *not* the bridge bot, try and get the bridge bot to
                // join them to the room.
                if (userId !== this.appservice.botUserId) {
                    const client = this.appservice.botIntent.underlyingClient;
                    const roomId = yield client.resolveRoom(roomIdOrAlias);
                    try {
                        // First start with having the bridge bot invite the user to the room
                        yield client.inviteUser(userId, roomId);
                    }
                    catch (inviteErr) {
                        // The invite failed - use the underlying join strategy to join the room, just in case.
                        // If there's no join strategy, we want to fall through to an error.
                        if (this.underlyingStrategy)
                            return this.underlyingStrategy.joinRoom(roomId, userId, apiCall);
                        throw inviteErr;
                    }
                    // The invite succeeded - use the underlying join strategy to join the room or just call use
                    // the apiCall if no strategy exists. We are expecting success.
                    if (this.underlyingStrategy)
                        return this.underlyingStrategy.joinRoom(roomId, userId, apiCall);
                    else
                        return apiCall(roomId);
                }
                else if (this.underlyingStrategy) {
                    // If the user being joined *is* the bridge bot, try and use the join strategy to join.
                    return this.underlyingStrategy.joinRoom(roomIdOrAlias, userId, apiCall);
                }
                // Finally, if all else fails, throw.
                throw err;
            }
        });
    }
}
exports.AppserviceJoinRoomStrategy = AppserviceJoinRoomStrategy;
