"use strict";
// Copyright 2022 - 2024 Gnuxie <Gnuxie@protonmail.com>
// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// SPDX-License-Identifier: Apache-2.0
//
// SPDX-FileAttributionText: <text>
// This modified file incorporates work from mjolnir
// https://github.com/matrix-org/mjolnir
// </text>
// SPDX-FileAttributionText: <text>
// This modified file incorporates work from matrix-protection-suite
// https://github.com/Gnuxie/matrix-protection-suite
// </text>
// SPDX-FileAttributionText: <text>
// This modified file incorporates work from typescript-result
// https://github.com/Gnuxie/typescript-result
// </text>
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResultError = void 0;
exports.Ok = Ok;
exports.Err = Err;
exports.isOk = isOk;
exports.isError = isError;
exports.ExpectError = ExpectError;
/**
 * @param ok The value indicating a successful result.
 * @returns Return an Result that was a success with the value ok.
 */
function Ok(ok) {
    return { ok, isOkay: true, match, expect };
}
/**
 * @param error The value indicating a failed result.
 * @returns An `Result` that was a failure with the error value.
 */
function Err(error) {
    return { error, isOkay: false, match, elaborate, expect };
}
/**
 * Check an `Result` was a success, can be used as a type assertion.
 * @param result An `Result` to check the success of.
 * @returns `true` if the `Result` was a success.
 */
function isOk(result) {
    return result.isOkay;
}
/**
 * Check an `Result` was a failure, can be used as a type assertion.
 * @param result The `Result` to check the success of.
 * @returns `true` if the `Result` was a failure.
 */
function isError(result) {
    return !result.isOkay;
}
function elaborate(message) {
    this.error.elaborate(message);
    return this;
}
function match(ok, error) {
    if (isError(this)) {
        return error(this.error);
    }
    else {
        return ok(this.ok);
    }
}
function ExpectError(result, elaboration) {
    if (isError(result)) {
        result.elaborate(elaboration);
        throw result.error.toExpectError();
    }
    return result.ok;
}
function expect(elaboration) {
    return ExpectError(this, elaboration);
}
/**
 * An extensible representation of an Error that describes what went wrong in a
 * a standard way.
 * @see {@link ActionException}
 */
class ResultError {
    constructor(message, elaborations = []) {
        this.message = message;
        this.elaborations = elaborations;
        // nothing to do.
    }
    /**
     * Convienant factory method to wrap an `ResultError` into an `Result`.
     * @param message The message for the `ResultError` that concisely describes the problem.
     * @param _options This exists so that the method is extensible by subclasses.
     * Otherwise they wouldn't be able to pass other constructor arguments through this method.
     * @returns An `Result` with a `ResultError` as the `Error` value.
     */
    static Result(message, _options = {}) {
        return Err(new ResultError(message));
    }
    /**
     * Elaborate on an ResultError that has been passed down the call stack.
     * Since we may need to offer a better explanation in a higher level context.
     * For example, there may be an ActionException relating to a network error,
     * but there is no explanation for what the caller was attempting to do.
     * So we can use this in the caller code to elaborate on the error.
     * @param message A short message to contextualise the action,
     * For example: "Failed to join the provided policy room.".
     * @returns This ResultError.
     */
    elaborate(message) {
        this.elaborations.push(message);
        return this;
    }
    getElaborations() {
        return this.elaborations;
    }
    get mostRelevantElaboration() {
        var _a;
        return (_a = this.elaborations.at(-1)) !== null && _a !== void 0 ? _a : this.message;
    }
    toReadableString() {
        if (this.elaborations.length === 0) {
            return this.message;
        }
        else {
            return `${this.elaborations.join("\nelaborated from: ")}\ncaused by: ${this.message}`;
        }
    }
    toString() {
        return this.toReadableString();
    }
    toExpectError() {
        return new TypeError(this.toReadableString());
    }
}
exports.ResultError = ResultError;
//# sourceMappingURL=Result.js.map