"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CUSTOM_HEADER_X_WEBSOCKET_ID = void 0;
exports.webHTTP = webHTTP;
const NOOP_1 = require("../../../../NOOP");
const EventSource_1 = require("../../../../system/platform/api/network/EventSource");
const id_1 = require("../../../../util/id");
const intercept_1 = require("./intercept");
exports.CUSTOM_HEADER_X_WEBSOCKET_ID = 'X-WebSocket-Id';
function webHTTP(window, opt) {
    const { fetch } = window;
    const http = {
        fetch: (0, intercept_1.__intercept__fetch)(fetch),
        createServer: (system, opt) => {
            return {
                listen: (port, handler) => {
                    const { cache: { servers, eventSources }, api: { window: { nextTick }, }, intercept, } = system;
                    if (servers[port]) {
                        throw new Error(`port ${port} is already in use`);
                    }
                    servers[port] = { opt, handler };
                    const handler_ = async (req) => {
                        const response = await handler(req);
                        if (req.method === 'GET' &&
                            req.headers['Accept'] === 'text/event-stream') {
                            const internalId = req.headers[EventSource_1.CUSTOM_HEADER_X_EVENT_SOURCE_ID] ?? '';
                            const eventSource = eventSources[internalId];
                            if (internalId) {
                                if (response.status === 200 &&
                                    response.headers['Content-Type'] === 'text/event-stream') {
                                    if (eventSource) {
                                        eventSource.onopen(new Event('open'));
                                        if (response.body instanceof ReadableStream) {
                                            nextTick(async () => {
                                                await response.body
                                                    .pipeThrough(new TextDecoderStream())
                                                    .pipeTo(new WritableStream({
                                                    write(data) {
                                                        eventSource.onmessage(new MessageEvent('message', {
                                                            data,
                                                        }));
                                                    },
                                                    close() {
                                                        eventSource.readyState = EventSource.CLOSED;
                                                        eventSource.onerror(new Event('error'));
                                                    },
                                                    abort() {
                                                        eventSource.readyState = EventSource.CLOSED;
                                                        eventSource.onerror(new Event('error'));
                                                    },
                                                }));
                                            });
                                        }
                                    }
                                }
                            }
                        }
                        return response;
                    };
                    const unlisten = intercept({
                        urls: [`http://localhost:${port}`, `ws://localhost:${port}`],
                    }, handler_);
                    return () => {
                        delete servers[port];
                        unlisten();
                    };
                },
            };
        },
        // @ts-ignore
        EventSource: window.EventSource,
        handleUpgrade: async function (request, response, ws, wss) {
            const socket = {
                send: function (data) {
                    const client = ws[id];
                    client.onmessage(new MessageEvent('message', { data }));
                },
                onmessage: NOOP_1.NOOP,
                onclose: NOOP_1.NOOP,
            };
            const id = (0, id_1.uuidNotIn)(wss);
            response.set({
                url: request.url,
                status: 200, // 101
                statusText: 'OK',
                redirected: false,
                bodyUsed: false,
                type: 'basic',
                headers: {
                    Connection: 'Upgrade',
                    Upgrade: 'websocket',
                    'Sec-WebSocket-Accept': '',
                    [exports.CUSTOM_HEADER_X_WEBSOCKET_ID]: id,
                },
                body: '',
                ok: true,
            });
            wss[id] = socket;
            return socket;
        },
    };
    return http;
}
//# sourceMappingURL=http.js.map