"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.startServer = startServer;
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable no-console */
const fs_1 = __importDefault(require("fs"));
const http_1 = __importDefault(require("http"));
const path_1 = __importDefault(require("path"));
const util_1 = require("util");
const cors_1 = __importDefault(require("@koa/cors"));
const ejs_1 = __importDefault(require("ejs"));
const koa_1 = __importDefault(require("koa"));
const koa_mount_1 = __importDefault(require("koa-mount"));
const ide_core_common_1 = require("@opensumi/ide-core-common");
const const_1 = require("@opensumi/ide-core-common/lib/const");
const ide_core_node_1 = require("@opensumi/ide-core-node");
const env = __importStar(require("./env"));
const openBrowser_1 = require("./openBrowser");
const ALLOW_MIME = {
    gif: 'image/gif',
    jpg: 'image/jpeg',
    png: 'image/png',
    svg: 'image/svg+xml',
    ttf: 'font/ttf',
    eot: 'font/eot',
    otf: 'font/otf',
    woff: 'font/woff',
    woff2: 'font/woff2',
    js: 'application/javascript',
    css: 'text/css',
};
const CLI_DEVELOPMENT_PATH = env.CLI_DEVELOPMENT_PATH;
const deviceIp = env.CLIENT_IP;
const extensionDir = path_1.default.join(CLI_DEVELOPMENT_PATH, 'extensions');
async function readPkgUp() {
    const pkgJsonStr = await (0, util_1.promisify)(fs_1.default.readFile)(path_1.default.resolve(__dirname, '../../package.json'), 'utf8');
    try {
        return JSON.parse(pkgJsonStr);
    }
    catch (err) {
        console.warn('json parse failed with:', pkgJsonStr);
        console.warn(err);
    }
    return {};
}
async function startServer(serverParams, ideAppOpts) {
    const { port = 50999, workspaceDir = __dirname, extensionCandidate = [__dirname], isDev, extHostPath, watchServerPort, } = serverParams;
    if (isDev) {
        process.env.IS_DEV = '1';
    }
    process.env.EXT_MODE = 'js';
    process.env.KTLOG_SHOW_DEBUG = '1';
    const app = new koa_1.default();
    const deferred = new ide_core_common_1.Deferred();
    // @ts-ignore
    app.use((0, cors_1.default)());
    let opts = {
        webSocketHandler: [],
        use: app.use.bind(app),
        marketplace: {
            endpoint: const_1.DEFAULT_OPENVSX_REGISTRY,
            showBuiltinExtensions: true,
            extensionDir: path_1.default.join(CLI_DEVELOPMENT_PATH, 'extensions'),
        },
        extHost: extHostPath || path_1.default.join(__dirname, '../hosted/ext.process.js'),
        logDir: path_1.default.join(CLI_DEVELOPMENT_PATH, 'logs'),
        logLevel: ide_core_common_1.LogLevel.Verbose,
        staticAllowPath: [extensionDir, ...extensionCandidate],
    };
    if (ideAppOpts.serverAppOpts) {
        opts = {
            ...opts,
            ...ideAppOpts.serverAppOpts,
        };
    }
    const serverApp = new ide_core_node_1.ServerApp(opts);
    const server = http_1.default.createServer(app.callback());
    await serverApp.start(server);
    app.use((0, koa_mount_1.default)('/', async (ctx) => {
        console.log('REQUEST URL:', ctx.url);
        let staticPath;
        let _path = ctx.url;
        if (_path.startsWith('/webview')) {
            staticPath = path_1.default.join(__dirname, `./${_path.split('?')[0]}`);
        }
        else if (_path === '/' || _path.endsWith('.html')) {
            _path = '/index.html';
            staticPath = path_1.default.join(__dirname, '../browser/index.html');
        }
        else {
            staticPath = path_1.default.join(__dirname, `../browser${_path}`);
        }
        const contentType = ALLOW_MIME[path_1.default.extname(_path).slice(1)];
        if (!fs_1.default.existsSync(staticPath)) {
            console.warn(`Load ${staticPath} failed.`);
            ctx.status = 404;
            ctx.body = 'Not Found.';
            return;
        }
        let content = fs_1.default.readFileSync(staticPath).toString();
        if (_path === '/index.html') {
            const assets = fs_1.default.readFileSync(path_1.default.join(__dirname, '../browser/assets.json')).toString();
            const config = {
                ideWorkspaceDir: workspaceDir,
                extensionDir,
                extensionCandidate,
                port,
                wsPath: `ws://${deviceIp}:${port}`,
                staticServicePath: `http://${deviceIp}:${port}`,
                webviewEndpoint: `http://${deviceIp}:${port}/webview`,
                watchServerPath: `ws://${deviceIp}:${watchServerPort}`,
            };
            const pkg = await readPkgUp();
            const meta = {
                ideVersion: pkg.dependencies['@opensumi/ide-core-common'],
                engineVersion: pkg.version,
            };
            content = ejs_1.default.compile(content, {})({
                config,
                meta,
                assets: JSON.parse(assets),
                clientAppOpts: ideAppOpts.clientAppOpts || {},
            });
        }
        ctx.set('Content-Type', contentType);
        ctx.body = content;
    }));
    server.on('error', (err) => {
        deferred.reject(err);
        console.error('server error: ' + err.message);
        setTimeout(process.exit, 0, 1);
    });
    server.listen(port, () => {
        console.log(`Server listen on port ${port}`);
        (0, openBrowser_1.openBrowser)(`http://${deviceIp}:${port}`);
        console.log(`
      The service started successfully, please click http://${deviceIp}:${port} to access the OpenSumi IDE.
    `);
        deferred.resolve(server);
    });
    return deferred.promise;
}
