"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require('path');
const copy = require('recursive-copy');
const fs = require('fs');
const EventEmitter = require("events");
const runner_1 = require("../common/runner");
const const_1 = require("../common/const");
const ws_1 = require("../server/ws");
class Runner extends EventEmitter {
    constructor(options, type) {
        super();
        this.on('error', e => {
            console.error(e);
        });
        this.checkEnv();
        this.init(options, type);
    }
    init(options, type) {
        this.type = type;
        this.config = Object.assign({}, options);
    }
    async startServer() {
        if (this.wsServer) {
            return this.wsServer;
        }
        const config = this.config;
        this.wsServer = new ws_1.default({
            staticFolder: config.jsBundleFolderPath,
        });
        await this.wsServer.init();
    }
    checkEnv() {
    }
    transmitEvent(outEvent) {
        outEvent.on(runner_1.messageType.outputError, message => {
            this.emit(runner_1.messageType.outputError, message);
        });
        outEvent.on(runner_1.messageType.outputLog, message => {
            this.emit(runner_1.messageType.outputLog, message);
        });
    }
    async setNativeConfig() {
        console.error('Not define `setNativeConfig`');
    }
    async copyJsBundle() {
        const options = {
            filter: ['**/*.js', '!**/*.web.js'],
            overwrite: true,
        };
        const { jsBundleFolderPath, projectPath } = this.config;
        if (const_1.PLATFORM_TYPES.ios) {
            await copy(path.join(jsBundleFolderPath), path.join(projectPath, 'bundlejs/'), options);
        }
        if (const_1.PLATFORM_TYPES.android) {
            await copy(path.join(jsBundleFolderPath), path.join(projectPath, 'app/src/main/assets/dist'), options);
        }
    }
    watchFileChange() {
        const config = this.config;
        const entryFileName = config.jsBundleEntry;
        if (this.filesWatcher) {
            this.filesWatcher.close();
        }
        this.filesWatcher = fs.watch(this.config.jsBundleFolderPath, {
            recursive: true,
        }, (type, name) => {
            if (/\w*\.web\.js$/.test(name)) {
                return;
            }
            if (name === entryFileName) {
                const wsServer = this.wsServer;
                const serverInfo = wsServer.getServerInfo();
                const ws = wsServer.getWs();
                if (!ws) {
                    return;
                }
                ws.send(JSON.stringify({
                    method: 'WXReloadBundle',
                    params: `http://${serverInfo.hostname}:${serverInfo.port}/${entryFileName}`,
                }));
            }
        });
        return true;
    }
    async buildNative(options) {
        console.error('Not define `updateList`');
    }
    async installAndLaunchApp(appPath) {
        console.error('Not define `installAndLaunchApp`');
    }
    async run(options) {
        let appPath;
        try {
            this.emit(runner_1.messageType.state, runner_1.runnerState.start);
            await this.startServer();
            this.emit(runner_1.messageType.state, runner_1.runnerState.startServerDone);
            await this.setNativeConfig();
            this.emit(runner_1.messageType.state, runner_1.runnerState.setNativeConfigDone);
            await this.copyJsBundle();
            this.emit(runner_1.messageType.state, runner_1.runnerState.copyJsBundleDone);
            this.watchFileChange();
            this.emit(runner_1.messageType.state, runner_1.runnerState.watchFileChangeDone);
            appPath = await this.buildNative(options);
            this.emit(runner_1.messageType.state, runner_1.runnerState.buildNativeDone);
            await this.installAndLaunchApp(appPath);
            this.emit(runner_1.messageType.state, runner_1.runnerState.installAndLaunchAppDone);
            this.emit(runner_1.messageType.state, runner_1.runnerState.done);
        }
        catch (error) {
            throw error;
        }
    }
    dispose() {
        this.filesWatcher.close();
        this.wsServer.dispose();
    }
}
exports.default = Runner;
