"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const definitions_1 = require("./definitions");
const socket_io_1 = __importDefault(require("socket.io"));
const http = __importStar(require("http"));
const shell_1 = require("../shell");
const fs_1 = require("fs");
class SocketIOProjectLinkerServer {
    constructor(project) {
        this.project = project;
    }
    feedback(msg) {
        if (!this.socket) {
            return;
        }
        this.socket.emit(definitions_1.EVENT_CHANNEL, {
            type: 'feedback',
            message: msg,
        });
    }
    error(msg) {
        if (!this.socket) {
            return;
        }
        this.socket.emit(definitions_1.ERROR_CHANNEL, msg);
    }
    progress(type, data) {
        if (!this.socket) {
            return;
        }
        this.socket.emit(definitions_1.EVENT_CHANNEL, Object.assign({ type: 'progress', action: type }, data));
    }
    start(PORT) {
        let io = socket_io_1.default(http);
        io.on('connection', (socket) => {
            this.socket = socket;
            console.log('a user connected');
            this.feedback(`Successfull connected to app builder. Current directory: ${process.cwd()}`);
            socket.on('disconnect', function () {
                console.log('user disconnected');
            });
            socket.on('getProjectInfo', () => {
                let directory = process.cwd();
                let projectInfo = {
                    directory: directory,
                    id: '1'
                };
                socket.emit('projectInfo', projectInfo);
            });
            socket.on('getConfig', () => {
                console.log('user requested config');
                this.project.reloadConfig();
                let data = {
                    tapConfig: this.project.tapConfig,
                    appConfig: this.project.appConfigSchema,
                    iotizeStudioConfig: this.project.iotizeStudioConfigString
                };
                socket.emit('config', data);
            });
            socket.on('setConfig', (newAppConfig) => __awaiter(this, void 0, void 0, function* () {
                console.log('user set config', newAppConfig);
                try {
                    let mergeConfig = Object.assign({
                        tapConfig: this.project.tapConfig,
                        appConfig: this.project.appConfigSchema,
                        iotizeStudioConfig: this.project.iotizeStudioConfigString
                    }, newAppConfig);
                    let projectConfigFile = `.iotize/project.config.json`;
                    fs_1.writeFileSync(projectConfigFile, JSON.stringify(mergeConfig, null, 4));
                    this.progress('setConfig', {
                        message: 'Writing configuration files...'
                    });
                    yield shell_1.shell.exec(`schematics @iotize/ionic-toolkit:app-config --config "${projectConfigFile}"`);
                    this.progress('setConfig', {
                        message: 'Generate project files...'
                    });
                    yield shell_1.shell.exec(`schematics @iotize/ionic-toolkit:generate`);
                    this.progress('setConfig', {
                        message: 'Installing dependencies...'
                    });
                    yield shell_1.shell.exec(`npm install`);
                    this.progress('setConfig', {
                        done: true
                    });
                    this.feedback(`App refresh successful!`);
                }
                catch (err) {
                    this.error({
                        message: `Generation failed. ${err.message}`,
                        code: 'GenerationFailed',
                        action: 'setConfig'
                    });
                }
            }));
            socket.on('schematic', (name) => {
                this.project.logger.info(`running schematic: "${name}"`);
                // schematic(name, {})(host, context);
                try {
                    let result = shell_1.shell.execSync(`schematics @iotize/ionic-toolkit:${name}`);
                    io.emit('schematic-result', result);
                }
                catch (err) {
                    console.warn('Schematic error: ', err);
                    this.error({
                        message: `Schematic error. ${err.message}`,
                        code: 'SchematicError'
                    });
                }
            });
            socket.on('serve', (options) => {
                this.project.logger.info(`serving app`);
                // shell.exec(`ng serve --port ${options.port} &`);
            });
        });
        let server = io.listen(PORT);
        this.project.context.logger.info(`socket server waiting ${PORT} ...`);
    }
}
exports.SocketIOProjectLinkerServer = SocketIOProjectLinkerServer;
//# sourceMappingURL=socketio-project-linker-server.js.map