/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module RpcInterface
 */
import { BeEvent } from "@itwin/core-bentley";
import { RpcConfiguration } from "./RpcConfiguration";
import { RpcRequestStatus, RpcResponseCacheControl } from "./RpcConstants";
import { RpcInvocation } from "./RpcInvocation";
import { RpcMarshaling } from "./RpcMarshaling";
/** @internal */
export var RpcRequestFulfillment;
(function (RpcRequestFulfillment) {
    async function forUnknownError(request, error) {
        const result = RpcMarshaling.serialize(undefined, error);
        return {
            interfaceName: request.operation.interfaceDefinition,
            id: request.id,
            result,
            rawResult: error,
            status: RpcRequestStatus.Rejected,
        };
    }
    RpcRequestFulfillment.forUnknownError = forUnknownError;
})(RpcRequestFulfillment || (RpcRequestFulfillment = {}));
/** Documents changes to the RPC protocol version.
 * @internal
 */
export var RpcProtocolVersion;
(function (RpcProtocolVersion) {
    RpcProtocolVersion[RpcProtocolVersion["None"] = 0] = "None";
    RpcProtocolVersion[RpcProtocolVersion["IntroducedNoContent"] = 1] = "IntroducedNoContent";
    RpcProtocolVersion[RpcProtocolVersion["IntroducedStatusCategory"] = 2] = "IntroducedStatusCategory";
})(RpcProtocolVersion || (RpcProtocolVersion = {}));
/** An application protocol for an RPC interface.
 * @internal
 */
export class RpcProtocol {
    /** Events raised by all protocols. See [[RpcProtocolEvent]] */
    static events = new BeEvent();
    /** A version code that identifies the RPC protocol capabilties of this endpoint. */
    static protocolVersion = RpcProtocolVersion.IntroducedStatusCategory;
    /** The name of the RPC protocol version header. */
    protocolVersionHeaderName = "";
    /** Events raised by the protocol. See [[RpcProtocolEvent]] */
    events = new BeEvent();
    /** The configuration for the protocol. */
    configuration;
    /** The RPC invocation class for this protocol. */
    invocationType = RpcInvocation;
    serializedClientRequestContextHeaderNames = {
        /** The name of the request id header. */
        id: "",
        /** The name of the application id header  */
        applicationId: "",
        /** The name of the version header. */
        applicationVersion: "",
        /** The name of the session id header  */
        sessionId: "",
        /** The name of the authorization header. */
        authorization: "",
    };
    /** If greater than zero, specifies where to break large binary request payloads. */
    transferChunkThreshold = 0;
    /** Used by protocols that can transmit stream values natively. */
    preserveStreams = false;
    /** Used by protocols that can transmit IModelRpcProps values natively. */
    checkToken = false;
    /** Used by protocols that support user-defined status codes. */
    supportsStatusCategory = false;
    /** If checkToken is true, will be called on the backend to inflate the IModelRpcProps for each request. */
    inflateToken(tokenFromBody, _request) { return tokenFromBody; }
    /** Override to supply the status corresponding to a protocol-specific code value. */
    getStatus(code) {
        return code;
    }
    /** Override to supply the protocol-specific code corresponding to a status value. */
    getCode(status) {
        return status;
    }
    /** Override to supply the protocol-specific path value for an RPC operation. */
    supplyPathForOperation(operation, _request) {
        return JSON.stringify(operation);
    }
    /** Override to supply the operation for a protocol-specific path value. */
    getOperationFromPath(path) {
        return JSON.parse(path);
    }
    /** Obtains the implementation result on the backend for an RPC operation request. */
    async fulfill(request) {
        return new (this.invocationType)(this, request).fulfillment;
    }
    /** Serializes a request. */
    async serialize(request) {
        const serializedContext = await RpcConfiguration.requestContext.serialize(request);
        return {
            ...serializedContext,
            operation: {
                interfaceDefinition: request.operation.interfaceDefinition.interfaceName,
                operationName: request.operation.operationName,
                interfaceVersion: request.operation.interfaceVersion,
            },
            method: request.method,
            path: request.path,
            parameters: RpcMarshaling.serialize(request.protocol, request.parameters),
            caching: RpcResponseCacheControl.None,
            protocolVersion: RpcProtocol.protocolVersion,
        };
    }
    /** Constructs a protocol. */
    constructor(configuration) {
        this.configuration = configuration;
        this.events.addListener((type, object) => RpcProtocol.events.raiseEvent(type, object));
    }
    /** @internal */
    onRpcClientInitialized(_definition, _client) { }
    /** @internal */
    onRpcImplInitialized(_definition, _impl) { }
    /** @internal */
    onRpcClientTerminated(_definition, _client) { }
    /** @internal */
    onRpcImplTerminated(_definition, _impl) { }
}
//# sourceMappingURL=RpcProtocol.js.map