/*---------------------------------------------------------------------------------------------
* 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 { BentleyError, Logger } from "@itwin/core-bentley";
import { CommonLoggerCategory } from "../../CommonLoggerCategory";
import { RpcContentType, RpcRequestStatus, WEB_RPC_CONSTANTS } from "../core/RpcConstants";
import { RpcProtocol } from "../core/RpcProtocol";
import { RpcOpenAPIDescription } from "./OpenAPI";
import { WebAppRpcLogging } from "./WebAppRpcLogging";
import { WebAppRpcRequest } from "./WebAppRpcRequest";
/** The HTTP application protocol.
 * @internal
 */
export class WebAppRpcProtocol extends RpcProtocol {
    preserveStreams = true;
    /** Convenience handler for an RPC operation get request for an HTTP server. */
    async handleOperationGetRequest(req, res) {
        return this.handleOperationPostRequest(req, res);
    }
    /** Convenience handler for an RPC operation post request for an HTTP server. */
    async handleOperationPostRequest(req, res) {
        let request;
        try {
            request = await WebAppRpcRequest.parseRequest(this, req);
        }
        catch (error) {
            const message = BentleyError.getErrorMessage(error);
            Logger.logError(CommonLoggerCategory.RpcInterfaceBackend, `Failed to parse request: ${message}`, BentleyError.getErrorMetadata(error));
            res.status(400);
            res.send(JSON.stringify({ message, isError: true }));
            return;
        }
        const fulfillment = await this.fulfill(request);
        await WebAppRpcRequest.sendResponse(this, request, fulfillment, req, res);
    }
    /** Convenience handler for an OpenAPI description request for an HTTP server. */
    handleOpenApiDescriptionRequest(_req, res) {
        const description = JSON.stringify(this.openAPIDescription);
        res.send(description);
    }
    /** Converts an HTTP content type value to an RPC content type value. */
    static computeContentType(httpType) {
        if (!httpType)
            return RpcContentType.Unknown;
        if (httpType.indexOf(WEB_RPC_CONSTANTS.ANY_TEXT) === 0) {
            return RpcContentType.Text;
        }
        else if (httpType.indexOf(WEB_RPC_CONSTANTS.BINARY) === 0) {
            return RpcContentType.Binary;
        }
        else if (httpType.indexOf(WEB_RPC_CONSTANTS.MULTIPART) === 0) {
            return RpcContentType.Multipart;
        }
        else {
            return RpcContentType.Unknown;
        }
    }
    /** An optional prefix for RPC operation URI paths. */
    pathPrefix = "";
    /** The RPC request class for this protocol. */
    requestType = WebAppRpcRequest;
    /** Supplies the status corresponding to a protocol-specific code value. */
    getStatus(code) {
        switch (code) {
            case 404: return RpcRequestStatus.NotFound;
            case 202: return RpcRequestStatus.Pending;
            case 200: return RpcRequestStatus.Resolved;
            case 500: return RpcRequestStatus.Rejected;
            case 204: return RpcRequestStatus.NoContent;
            case 502: return RpcRequestStatus.BadGateway;
            case 503: return RpcRequestStatus.ServiceUnavailable;
            case 504: return RpcRequestStatus.GatewayTimeout;
            case 408: return RpcRequestStatus.RequestTimeout;
            case 429: return RpcRequestStatus.TooManyRequests;
            default: return RpcRequestStatus.Unknown;
        }
    }
    /** Supplies the protocol-specific code corresponding to a status value. */
    getCode(status) {
        switch (status) {
            case RpcRequestStatus.NotFound: return 404;
            case RpcRequestStatus.Pending: return 202;
            case RpcRequestStatus.Resolved: return 200;
            case RpcRequestStatus.Rejected: return 500;
            case RpcRequestStatus.NoContent: return 204;
            case RpcRequestStatus.BadGateway: return 502;
            case RpcRequestStatus.ServiceUnavailable: return 503;
            case RpcRequestStatus.GatewayTimeout: return 504;
            case RpcRequestStatus.RequestTimeout: return 408;
            case RpcRequestStatus.TooManyRequests: return 429;
            default: return 501;
        }
    }
    supportsStatusCategory = true;
    /** Whether an HTTP status code indicates a request timeout. */
    isTimeout(code) {
        return code === 504;
    }
    /** An OpenAPI-compatible description of this protocol.
     * @internal
     */
    get openAPIDescription() { return new RpcOpenAPIDescription(this); }
    /** Constructs an HTTP protocol. */
    constructor(configuration) {
        super(configuration);
        this.events.addListener(async (event, object) => WebAppRpcLogging.logProtocolEvent(event, object));
    }
}
//# sourceMappingURL=WebAppRpcProtocol.js.map