"use strict";
/*
 * Tencent is pleased to support the open source community by making
 * Hippy available.
 *
 * Copyright (C) 2017-2019 THL A29 Limited, a Tencent company.
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.killChildProcess = exports.startChrome = exports.startIWDP = exports.startTunnel = exports.tunnelEmitter = exports.TUNNEL_EVENT = void 0;
const tslib_1 = require("tslib");
const child_process_1 = require("child_process");
const events_1 = require("events");
const path_1 = tslib_1.__importDefault(require("path"));
const os_1 = tslib_1.__importDefault(require("os"));
const safe_1 = tslib_1.__importDefault(require("colors/safe"));
const open_1 = require("@debug-server-next/utils/open");
const enum_1 = require("@debug-server-next/@types/enum");
const device_manager_1 = require("@debug-server-next/device-manager");
const log_1 = require("@debug-server-next/utils/log");
const config_1 = require("@debug-server-next/config");
const url_1 = require("@debug-server-next/utils/url");
const adb_1 = require("./adb");
const childProcessLog = new log_1.Logger('child-process', enum_1.WinstonColor.Magenta);
const tunnelLog = new log_1.TunnelLogger('tunnel', enum_1.WinstonColor.BrightRed);
let proxyProcess;
exports.TUNNEL_EVENT = 'message';
exports.tunnelEmitter = new events_1.EventEmitter();
const startTunnel = async (cb) => {
    global.addon.addEventListener((event, data) => {
        try {
            if (event !== "tunnel_log" /* TunnelEvent.TunnelLog */) {
                tunnelLog.verbose('tunnel event: %s', event);
            }
            if (event === "tunnel_recv_data" /* TunnelEvent.ReceiveData */) {
                exports.tunnelEmitter.emit(exports.TUNNEL_EVENT, data);
            }
            else {
                if (["tunnel_remove_device" /* TunnelEvent.RemoveDevice */, "tunnel_add_device" /* TunnelEvent.AddDevice */].indexOf(event) !== -1) {
                    if (event === "tunnel_remove_device" /* TunnelEvent.RemoveDevice */) {
                        childProcessLog.warn(safe_1.default.bold[enum_1.WinstonColor.Red]('device disconnected'));
                    }
                    if (event === "tunnel_add_device" /* TunnelEvent.AddDevice */) {
                        childProcessLog.info(safe_1.default.bold[enum_1.WinstonColor.Green]('device connected'));
                        // every time device connect, auto run adb reverse
                        (0, adb_1.startAdbProxy)();
                    }
                    device_manager_1.deviceManager.getDeviceList();
                }
                else if (event === "tunnel_app_connect" /* TunnelEvent.AppConnect */) {
                    device_manager_1.deviceManager.onAppConnect();
                }
                else if (event === "tunnel_app_disconnect" /* TunnelEvent.AppDisconnect */) {
                    device_manager_1.deviceManager.onAppDisconnect();
                }
                else if (event === "tunnel_log" /* TunnelEvent.TunnelLog */ && data) {
                    tunnelLog.verbose(data);
                }
                if (cb)
                    cb(event, data);
            }
        }
        catch (e) {
            tunnelLog.error('handle tunnel event error: %s', e === null || e === void 0 ? void 0 : e.stack);
        }
    });
    global.addon.tunnelStart(getTunnelOption());
};
exports.startTunnel = startTunnel;
const startIWDP = () => {
    const { iWDPPort } = global.debugAppArgv;
    const { iWDPStartPort, iWDPEndPort } = config_1.config;
    proxyProcess = (0, child_process_1.spawn)('ios_webkit_debug_proxy', ['--no-frontend', `--config=null:${iWDPPort},:${iWDPStartPort}-${iWDPEndPort}`], { detached: false });
    proxyProcess.unref();
    childProcessLog.info(`start IWDP on port ${iWDPPort}`);
    proxyProcess.stdout.on('data', (msg) => childProcessLog.verbose(msg.toString()));
    proxyProcess.stderr.on('data', (msg) => childProcessLog.verbose(msg.toString()));
    proxyProcess.on('error', (e) => {
        childProcessLog.error('IWDP error: %s', e === null || e === void 0 ? void 0 : e.stack);
    });
    proxyProcess.on('message', (msg) => {
        childProcessLog.verbose('IWDP message: %j', msg);
    });
    proxyProcess.on('close', (code) => {
        childProcessLog.warn(`IWDP close with code: ${code}`);
    });
};
exports.startIWDP = startIWDP;
const startChrome = async () => {
    const { open: openChrome } = global.debugAppArgv;
    if (openChrome) {
        const url = (0, url_1.getHomeUrl)();
        try {
            (0, open_1.startBrowserProcess)(undefined, url);
        }
        catch (e) {
            childProcessLog.error('open %s by chrome failed, please open manually, %s', url, e === null || e === void 0 ? void 0 : e.stack);
        }
    }
};
exports.startChrome = startChrome;
const killChildProcess = () => {
    var _a;
    (_a = global.__CHILD_PROCESS__) === null || _a === void 0 ? void 0 : _a.forEach((cp) => {
        cp === null || cp === void 0 ? void 0 : cp.kill('SIGKILL');
    });
    if (!proxyProcess)
        return;
    childProcessLog.warn('server exit, do some clean...');
    proxyProcess === null || proxyProcess === void 0 ? void 0 : proxyProcess.kill('SIGKILL');
    proxyProcess = null;
};
exports.killChildProcess = killChildProcess;
function getTunnelOption() {
    const { iWDPPort, log } = global.debugAppArgv;
    const { iWDPStartPort, iWDPEndPort } = config_1.config;
    const iWDPParams = [
        '--no-frontend',
        log === enum_1.LogLevel.Silly ? '--debug' : '',
        `--config=null:${iWDPPort},:${iWDPStartPort}-${iWDPEndPort}`,
    ].filter(Boolean);
    let tunnelOption;
    if (os_1.default.type() === enum_1.OSType.Darwin) {
        tunnelOption = {
            adb_path: path_1.default.join(__dirname, '../build/mac/adb'),
            iwdp: {
                iwdp_params: iWDPParams,
                iwdp_listen_port: iWDPPort,
            },
            only_use_iwdp: 0,
        };
    }
    if (os_1.default.type() === enum_1.OSType.Windows) {
        tunnelOption = {
            adb_path: path_1.default.join(__dirname, '../build/win/adb.exe'),
            iwdp: {
                iwdp_params: iWDPParams,
                iwdp_listen_port: iWDPPort,
                iwdp_path: path_1.default.join(__dirname, '../build/win/iwdp1.8.8/ios_webkit_debug_proxy.exe'),
            },
            only_use_iwdp: 0,
            iproxy_path: path_1.default.join(__dirname, '../build/win/idevice/iproxy.exe'),
            idevice_info_path: path_1.default.join(__dirname, '../build/win/idevice/ideviceinfo.exe'),
        };
    }
    childProcessLog.info('tunnel option: %j', tunnelOption);
    return tunnelOption;
}
