"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IrcCapabilities = void 0;
/**
 * A helper class to handle capabilities sent by the IRCd.
 */
class IrcCapabilities {
    constructor(onCapsList, onCapsConfirmed) {
        this.onCapsList = onCapsList;
        this.onCapsConfirmed = onCapsConfirmed;
    }
    static parseCapabilityString(caps) {
        var _a;
        const allCaps = caps.trim().split(' ');
        // Not all servers respond with the type of sasl supported.
        const saslTypes = (_a = allCaps.find((s) => s.startsWith('sasl='))) === null || _a === void 0 ? void 0 : _a.split('=')[1].split(',').map((s) => s.toUpperCase());
        if (saslTypes) {
            allCaps.push('sasl');
        }
        return {
            caps: new Set(allCaps),
            saslTypes: new Set(saslTypes),
        };
    }
    get capsReady() {
        return !!this.userCapabilites;
    }
    get supportsSasl() {
        if (!this.serverCapabilites) {
            throw Error('Server response has not arrived yet');
        }
        return this.serverCapabilites.caps.has('sasl');
    }
    /**
     * Check if the IRCD supports a given Sasl method.
     * @param method The method of SASL (e.g. 'PLAIN', 'EXTERNAL') to check support for. Case insensitive.
     * @param allowNoMethods Not all implementations support explicitly mentioning SASL methods,
     * so optionally we can return true here.
     * @returns True if supported, false otherwise.
     * @throws If the capabilites have not returned yet.
     */
    supportsSaslMethod(method, allowNoMethods = false) {
        if (!this.serverCapabilites) {
            throw Error('Server caps response has not arrived yet');
        }
        if (!this.serverCapabilites.caps.has('sasl')) {
            return false;
        }
        if (!this.serverCapabilites.saslTypes) {
            return allowNoMethods;
        }
        return this.serverCapabilites.saslTypes.has(method.toUpperCase());
    }
    /**
     * Handle an incoming `CAP` message.
     */
    onCap(message) {
        // E.g. CAP * LS :account-notify away-notify chghost extended-join multi-prefix
        // sasl=PLAIN,ECDSA-NIST256P-CHALLENGE,EXTERNAL tls account-tag cap-notify echo-message
        // solanum.chat/identify-msg solanum.chat/realhost
        const [, subCmd, parts] = message.args;
        if (subCmd === 'LS') {
            // Listing all caps
            this.serverCapabilites = IrcCapabilities.parseCapabilityString(parts);
            // We now need to request
            this.onCapsList();
        }
        // The target might be * or the nickname, for now just accept either.
        if (subCmd === 'ACK') {
            // Listing all caps
            this.userCapabilites = IrcCapabilities.parseCapabilityString(parts);
            this.onCapsConfirmed();
        }
    }
}
exports.IrcCapabilities = IrcCapabilities;
//# sourceMappingURL=capabilities.js.map