import logger from "./Logger";
import GracefulShutdown, { ShutdownPriority } from "./GracefulShutdown";
import "ejs";
import express from "express";
import { createServer } from "http";
export const ExpressStatic = express.static;
export const ExpressJson = express.json;
export const ExpressUrlEncoded = express.urlencoded;
export const ExpressRaw = express.raw;
export const createExpressApp = () => {
    return express();
};
class Express {
    static getRouter() {
        return express.Router();
    }
    static setupExpress() {
        this.app = express();
    }
    static getHttpServer() {
        return this.httpServer;
    }
    static getExpressApp() {
        if (!this.app) {
            this.setupExpress();
        }
        return this.app;
    }
    static async launchApplication(appName, port) {
        if (!this.app) {
            this.setupExpress();
        }
        if (!this.httpServer) {
            this.httpServer = createServer(this.app);
        }
        /*
         * On shutdown, stop accepting new connections first (before datastores are
         * drained) so in-flight requests can finish but new ones don't acquire
         * resources we're about to tear down. closeIdleConnections() drops idle
         * keep-alive sockets so server.close() doesn't block waiting on them; the
         * GracefulShutdown per-handler timeout bounds anything still in flight.
         */
        GracefulShutdown.registerHandler("HttpServer", ShutdownPriority.HttpServer, () => {
            return new Promise((resolve) => {
                if (!this.httpServer || !this.httpServer.listening) {
                    resolve();
                    return;
                }
                const server = this.httpServer;
                if (typeof server.closeIdleConnections === "function") {
                    server.closeIdleConnections();
                }
                server.close(() => {
                    resolve();
                });
            });
        });
        return new Promise((resolve) => {
            this.httpServer.listen((port === null || port === void 0 ? void 0 : port.toNumber()) || this.app.get("port"), () => {
                logger.debug(`${appName} server started on port: ${(port === null || port === void 0 ? void 0 : port.toNumber()) || this.app.get("port")}`);
                return resolve(this.app);
            });
        });
    }
}
export default Express;
export const headerValueToString = (value) => {
    if (Array.isArray(value)) {
        return value.length > 0 ? value[0] : undefined;
    }
    if (typeof value === "string" && value.trim().length > 0) {
        return value.trim();
    }
    return undefined;
};
export const extractDeviceInfo = (req) => {
    const body = (req.body || {});
    const data = body["data"] || {};
    const getValue = (key) => {
        const headerKey = key.toLowerCase();
        const camelKey = headerKey
            .split("-")
            .map((part, index) => {
            if (index === 0) {
                return part;
            }
            return part.charAt(0).toUpperCase() + part.slice(1);
        })
            .join("");
        return (headerValueToString(req.headers[`x-${headerKey}`]) ||
            headerValueToString(body[camelKey]) ||
            headerValueToString(data[camelKey]) ||
            headerValueToString(body[key]) ||
            headerValueToString(data[key]));
    };
    const result = {};
    const deviceName = getValue("device-name");
    if (deviceName) {
        result.deviceName = deviceName;
    }
    const deviceType = getValue("device-type");
    if (deviceType) {
        result.deviceType = deviceType;
    }
    const deviceOS = getValue("device-os");
    if (deviceOS) {
        result.deviceOS = deviceOS;
    }
    const deviceBrowser = getValue("device-browser");
    if (deviceBrowser) {
        result.deviceBrowser = deviceBrowser;
    }
    return result;
};
export const getClientIp = (req) => {
    var _a, _b, _c, _d;
    const forwarded = req.headers["x-forwarded-for"];
    if (Array.isArray(forwarded) && forwarded.length > 0) {
        return (_b = (_a = forwarded[0]) === null || _a === void 0 ? void 0 : _a.split(",")[0]) === null || _b === void 0 ? void 0 : _b.trim();
    }
    if (typeof forwarded === "string" && forwarded.trim().length > 0) {
        return (_c = forwarded.split(",")[0]) === null || _c === void 0 ? void 0 : _c.trim();
    }
    if ((_d = req.socket) === null || _d === void 0 ? void 0 : _d.remoteAddress) {
        return req.socket.remoteAddress;
    }
    return req.ip;
};
//# sourceMappingURL=Express.js.map