"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.saveDevPort = exports.normalizeWebpackConfig = exports.getWebpackConfig = void 0;
const tslib_1 = require("tslib");
const fs_1 = tslib_1.__importDefault(require("fs"));
const path_1 = tslib_1.__importDefault(require("path"));
const hippy_hmr_plugin_1 = tslib_1.__importDefault(require("@hippy/hippy-hmr-plugin"));
const qrcode_1 = tslib_1.__importDefault(require("qrcode"));
const safe_1 = require("colors/safe");
const log_1 = require("@/utils/log");
const url_1 = require("@/utils/url");
const config_1 = require("@/config");
const ip_1 = require("@/utils/ip");
const port_1 = require("@/utils/port");
const process_1 = require("@/utils/process");
tslib_1.__exportStar(require("./inject-entry"), exports);
const log = new log_1.Logger('webpack-util');
async function getWebpackConfig(configPath) {
    let webpackConfig;
    const webpackConfigPath = path_1.default.resolve(process.cwd(), configPath);
    if (configPath && fs_1.default.existsSync(webpackConfigPath)) {
        webpackConfig = await Promise.resolve().then(() => tslib_1.__importStar(require(webpackConfigPath)));
    }
    return (webpackConfig === null || webpackConfig === void 0 ? void 0 : webpackConfig.default) || webpackConfig;
}
exports.getWebpackConfig = getWebpackConfig;
function normalizeWebpackConfig(versionId, config) {
    const enableRemoteDebug = isRemoteDebugEnabled(config);
    if (!enableRemoteDebug)
        return log.warn('remote debug is disabled!');
    normalizeRemoteDebug(versionId, config);
    appendHMRPlugin(versionId, config);
}
exports.normalizeWebpackConfig = normalizeWebpackConfig;
function normalizeRemoteDebug(versionId, config) {
    var _a;
    var _b;
    config.devServer.remote = {
        protocol: 'http',
        host: '127.0.0.1',
        port: 38989,
        qrcode: false,
        proxy: '',
        ...(config.devServer.remote || {}),
    };
    (_a = (_b = config.devServer).autoLaunchHippyDebug) !== null && _a !== void 0 ? _a : (_b.autoLaunchHippyDebug = true);
    if (config.devServer.autoLaunchHippyDebug) {
        autoLaunchHippyDebug(config.devServer.remote);
    }
    const { protocol, host, port, qrcode: qrcodeFn } = config.devServer.remote;
    const publicPath = getPublicPath(versionId, config.devServer);
    config.output.publicPath = publicPath;
    log.warn(safe_1.bold(safe_1.yellow(`webpack publicPath is set as: ${config.output.publicPath}`)));
    const ignorePort = couldIgnorePort(protocol, port);
    const bundleUrl = url_1.makeUrl(`${config.output.publicPath}index.bundle`, {
        debugUrl: url_1.makeUrl(`${url_1.getWSProtocolByHttpProtocol(protocol)}://${host}${ignorePort ? '' : `:${port}`}/debugger-proxy`),
    });
    const homeUrl = `${protocol}://${host}${ignorePort ? '' : `:${port}`}/extensions/home.html?hash=${versionId}`;
    config.devServer.cb = () => {
        process.nextTick(() => {
            // only print qrcode when use remote debug server
            const needVersionId = needPublicPathWithVersionId(host, config.multiple);
            if (needVersionId)
                log.info('paste the following bundleUrl in app to open hippy page');
            log.info('bundleUrl: %s', safe_1.bold(safe_1.green(bundleUrl)));
            log.info('find debug page on: %s', safe_1.bold(safe_1.green(homeUrl)));
            if (needVersionId && qrcodeFn && typeof qrcodeFn === 'function') {
                const qrcodeStr = qrcodeFn(bundleUrl);
                log.info('bundleUrl QRCode scheme: %s', safe_1.bold(safe_1.green(qrcodeStr)));
                qrcode_1.default.toString(qrcodeStr, {
                    small: true,
                    type: 'terminal',
                }, (e, qrcodeStr) => {
                    if (e)
                        log.error('draw QRCode of bundleUrl failed: %j', (e === null || e === void 0 ? void 0 : e.stack) || e);
                    log.info('scheme qrcode:\n%s', qrcodeStr);
                });
            }
        });
    };
}
function appendHMRPlugin(versionId, config) {
    const hotManifestPublicPath = getPublicPath(versionId, config.devServer);
    const i = config.plugins.findIndex((plugin) => plugin.constructor.name === hippy_hmr_plugin_1.default.name);
    if (i !== -1) {
        config.plugins.splice(i, 1);
    }
    if (!config.devServer.hot && !config.devServer.liveReload)
        return;
    config.plugins.push(new hippy_hmr_plugin_1.default({ hotManifestPublicPath }));
}
/**
 * remote debug is enabled by default if enable webpack-dev-server
 */
function isRemoteDebugEnabled(webpackConfig) {
    return webpackConfig.devServer;
}
/**
 * when use debug-server-next in local, publicPath will append versionId if set devServer.multiple === true
 * and will always append versionId for remote
 */
function needPublicPathWithVersionId(host, multiple) {
    const isLocal = host === 'localhost' || host === '127.0.0.1';
    if (isLocal)
        return Boolean(multiple);
    return true;
}
function getPublicPath(versionId, { remote: { host, port, protocol }, multiple }) {
    const ignorePort = couldIgnorePort(protocol, port);
    if (!needPublicPathWithVersionId(host, multiple))
        return `${protocol}://${host}${ignorePort ? '' : `:${port}`}/`;
    return `${protocol}://${host}${ignorePort ? '' : `:${port}`}/${versionId}/`;
}
function couldIgnorePort(protocol, port) {
    const couldIgnore = (protocol === 'https' && Number(port) === 443) || (protocol === 'http' && Number(port) === 80);
    log.silly(couldIgnore);
    // TODO iOS doesn't support ignore port
    return false;
}
/**
 * hippy-dev process will save hmrPort to file,
 * hippy-debug process will auto reverse hmrPort when device reconnect.
 */
async function saveDevPort(hmrPort) {
    const { cachePath } = config_1.config;
    fs_1.default.mkdirSync(cachePath, { recursive: true });
    return fs_1.default.writeFileSync(config_1.config.hmrPortPath, String(hmrPort));
}
exports.saveDevPort = saveDevPort;
/**
 * auto launch hippy:debug if remote.host is local hostname
 */
async function autoLaunchHippyDebug({ protocol, host, port }) {
    if (protocol !== 'http')
        return;
    const hostList = await ip_1.getAllLocalHostname();
    if (!hostList.includes(host))
        return;
    const inUse = await port_1.isPortInUse(port);
    if (inUse)
        return;
    process_1.exec('node', [path_1.default.join(__dirname, '../../../dist/index-debug.js'), '--port', port]);
}
