#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// npm link --force
// npm i npm install --global --production windows-build-tools
const fs = require("fs");
const Logger_1 = require("./Logger");
Logger_1.Logger.configure(true, true);
Logger_1.Logger.enabled["cli"] = 7;
Logger_1.Logger.enabled["cliutil"] = 7;
const Config_1 = require("./Config");
const cliutil_1 = require("./nodeclient/cliutil");
const openflow_api_1 = require("@openiap/openflow-api");
const pm2util_1 = require("./nodeclient/pm2util");
const optionDefinitions = [
    { name: 'verbose', alias: 'v', type: Boolean },
    { name: 'authenticate', alias: 'a', type: Boolean },
    { name: 'init', type: Boolean },
    { name: 'install', alias: 'i', type: Boolean },
    { name: 'uninstall', alias: 'u', type: Boolean },
    { name: 'start', type: Boolean },
    { name: 'restart', type: Boolean },
    { name: 'stop', type: Boolean },
    { name: 'run', type: Boolean },
    { name: 'name', type: String, defaultOption: true },
    { name: 'config', type: String },
    { name: 'inspect', type: String },
    { name: 'networks', type: Boolean }
];
const commandLineArgs = require('command-line-args');
const path = require('path');
const readlineSync = require('readline-sync');
const envfile = require('envfile');
const { networkInterfaces } = require('os');
let options = null;
try {
    options = commandLineArgs(optionDefinitions);
    if (!options.init) {
        if (options.networks) {
            const nets = networkInterfaces();
            for (const name of Object.keys(nets)) {
                for (const net of nets[name]) {
                    // skip over non-ipv4 and internal (i.e. 127.0.0.1) addresses
                    if (net.family === 'IPv4' && !net.internal) {
                        Logger_1.Logger.instanse.info("cli", "", name + " " + net.address);
                    }
                }
            }
            process.exit();
        }
        if (options.name == null || options.name == "")
            throw new Error("Name is mandatory");
        if (options.name.endsWith(".env"))
            options.name = options.name.substring(0, options.name.length - 4);
        cliutil_1.servicename = options.name;
        cliutil_1.envfilename = options.name + ".env";
        cliutil_1.envfilepathname = path.join(process.cwd(), cliutil_1.envfilename);
        if (options.config != null && options.config != "")
            cliutil_1.envfilepathname = options.config;
        if (!(0, cliutil_1.isOpenFlow)()) {
            let parsedFile = envfile.parse(fs.readFileSync(cliutil_1.envfilepathname));
            if (parsedFile.jwt == null || parsedFile.jwt == "") {
                if (options.authenticate != true)
                    Logger_1.Logger.instanse.warn("cli", "", cliutil_1.envfilename + " is missing a jwt, switching to --authenticate");
                options.authenticate = true;
            }
        }
    }
}
catch (error) {
    Logger_1.Logger.instanse.error("cli", "", error.message ? error.message : error);
    printusage();
    process.exit();
}
function getToken() {
    return new Promise(async (resolve, reject) => {
        Logger_1.Logger.instanse.info("cli", "", "wsurl " + Config_1.Config.api_ws_url);
        let socket = new openflow_api_1.WebSocketClient(cliutil_1.logger, Config_1.Config.api_ws_url);
        socket.agent = "nodered-cli";
        socket.version = Config_1.Config.version;
        socket.events.on("onopen", async () => {
            try {
                const username = readlineSync.question('username? ');
                const password = readlineSync.question('password? ', { hideEchoBack: true });
                const result = await openflow_api_1.NoderedUtil.SigninWithUsername({ username, password, longtoken: true });
                Logger_1.Logger.instanse.info("cli", "", "signed in as " + result.user.name + " with id " + result.user._id);
                openflow_api_1.WebSocketClient.instance.user = result.user;
                openflow_api_1.WebSocketClient.instance.jwt = result.jwt;
                socket.close(1000, "Close by user");
                resolve(result.jwt);
                socket = null;
            }
            catch (error) {
                let closemsg = (error.message ? error.message : error);
                Logger_1.Logger.instanse.error("cli", "", error);
                socket.close(1000, closemsg);
                reject(closemsg);
                socket = null;
            }
        });
    });
}
async function doit() {
    try {
        if (options.init) {
            Logger_1.Logger.instanse.info("cli", "", "init");
            const files = fs.readdirSync(path.join(__dirname, ".."));
            for (let i = 0; i < files.length; i++) {
                let filename = files[i];
                if (path.extname(filename) == '.env') {
                    const target = path.join(process.cwd(), filename);
                    if (!fs.existsSync(target)) {
                        Logger_1.Logger.instanse.info("cli", "", "Creating " + filename);
                        filename = path.join(__dirname, "..", filename);
                        fs.copyFileSync(filename, target);
                        let parsedFile = envfile.parse(fs.readFileSync(target));
                        parsedFile.logpath = process.cwd();
                        fs.writeFileSync(target, envfile.stringify(parsedFile));
                    }
                    else {
                        Logger_1.Logger.instanse.info("cli", "", "Skipping " + filename + " already exists.");
                    }
                }
            }
        }
        else if (options.authenticate == true) {
            Logger_1.Logger.instanse.info("cli", "", "authenticate");
            if (await (0, pm2util_1.pm2exists)(cliutil_1.servicename)) {
                await (0, pm2util_1.pm2stop)(cliutil_1.servicename);
                await (0, pm2util_1.pm2delete)(cliutil_1.servicename);
            }
            try {
                Logger_1.Logger.instanse.info("cli", "", "isOpenFlow: " + (0, cliutil_1.isOpenFlow)());
                if (!(0, cliutil_1.isOpenFlow)()) {
                    (0, cliutil_1.loadenv)();
                    let jwt = await getToken();
                    let parsedFile = envfile.parse(fs.readFileSync(cliutil_1.envfilepathname));
                    parsedFile.jwt = jwt;
                    fs.writeFileSync(cliutil_1.envfilepathname, envfile.stringify(parsedFile));
                    openflow_api_1.WebSocketClient.instance.close(1000, "done");
                }
                (0, cliutil_1.loadenv)();
                await (0, pm2util_1.pm2start)({
                    name: cliutil_1.servicename,
                    script: __filename,
                    args: [cliutil_1.servicename, "--run", "--config", cliutil_1.envfilepathname]
                });
                Logger_1.Logger.instanse.info("cli", "", "Quit");
                (0, pm2util_1.pm2disconnect)();
            }
            catch (error) {
                Logger_1.Logger.instanse.error("cli", "", error);
            }
        }
        else if (options.install == true) {
            Logger_1.Logger.instanse.info("cli", "", "install");
            (0, cliutil_1.loadenv)();
            if (!await (0, pm2util_1.pm2exists)(cliutil_1.servicename)) {
                await (0, pm2util_1.pm2start)({
                    name: cliutil_1.servicename,
                    script: __filename,
                    args: [cliutil_1.servicename, "--run", "--config", cliutil_1.envfilepathname]
                });
                if (process.platform == "linux") {
                    try {
                        await (0, pm2util_1.pm2startup)("systemd");
                    }
                    catch (error) {
                        Logger_1.Logger.instanse.error("cli", "", error);
                    }
                }
                else if (process.platform != "win32") {
                    try {
                        await (0, pm2util_1.pm2startup)(process.platform);
                    }
                    catch (error) {
                        Logger_1.Logger.instanse.error("cli", "", error);
                    }
                }
                await (0, pm2util_1.pm2dump)();
            }
            else {
                await (0, pm2util_1.pm2restart)(cliutil_1.servicename);
            }
            (0, pm2util_1.pm2disconnect)();
        }
        else if (options.uninstall == true) {
            Logger_1.Logger.instanse.info("cli", "", "uninstall");
            if (await (0, pm2util_1.pm2exists)(cliutil_1.servicename)) {
                await (0, pm2util_1.pm2stop)(cliutil_1.servicename);
                await (0, pm2util_1.pm2delete)(cliutil_1.servicename);
                await (0, pm2util_1.pm2dump)();
            }
            else {
                Logger_1.Logger.instanse.error("cli", "", cliutil_1.servicename + " not found");
            }
            (0, pm2util_1.pm2disconnect)();
        }
        else if (options.start == true) {
            Logger_1.Logger.instanse.info("cli", "", "start");
            (0, cliutil_1.loadenv)();
            await (0, pm2util_1.pm2restart)(cliutil_1.servicename);
            (0, pm2util_1.pm2disconnect)();
        }
        else if (options.stop == true) {
            Logger_1.Logger.instanse.info("cli", "", "stop");
            await (0, pm2util_1.pm2stop)(cliutil_1.servicename);
            (0, pm2util_1.pm2disconnect)();
        }
        else if (options.restart == true) {
            Logger_1.Logger.instanse.info("cli", "", "restart");
            await (0, pm2util_1.pm2restart)(cliutil_1.servicename);
            (0, pm2util_1.pm2disconnect)();
        }
        else if (options.run == true) {
            (0, pm2util_1.pm2disconnect)();
            Logger_1.Logger.instanse.info("cli", "", "run");
            (0, cliutil_1.loadenv)();
            Logger_1.Logger.instanse.info("cli", "", "Starting as service " + cliutil_1.servicename);
            let index = path.join(__dirname, "/index.js");
            if (!fs.existsSync(index)) {
                index = path.join(__dirname, "dist", "/index.js");
            }
            Logger_1.Logger.instanse.info("cli", "", "run: " + index);
            require(index);
        }
        else {
            Logger_1.Logger.instanse.info("cli", "", "unknown, print usage");
            printusage();
        }
    }
    catch (error) {
        Logger_1.Logger.instanse.error("cli", "", error);
        process.exit();
    }
}
function printusage() {
    if (!(0, cliutil_1.isOpenFlow)()) {
        Logger_1.Logger.instanse.info("cli", "", "openflow-nodered-cli [--init][--install][--uninstall][--config][--start][--stop] name");
        Logger_1.Logger.instanse.info("cli", "", "   --init - Create sample environment files for running nodered");
        Logger_1.Logger.instanse.info("cli", "", "   --install - Install openflow as an service that runs at boot");
        Logger_1.Logger.instanse.info("cli", "", "   --uninstall - Uninstalls service, if openflow has been installed as an service");
        Logger_1.Logger.instanse.info("cli", "", "   --config - Prompt for credentials and create config");
        Logger_1.Logger.instanse.info("cli", "", "   --start - Will start the service with the given name");
        Logger_1.Logger.instanse.info("cli", "", "   --stop - Will stop the service with the given name");
        Logger_1.Logger.instanse.info("cli", "", "   name - Service and instance name");
        Logger_1.Logger.instanse.info("cli", "", "Will look for an envoriment file called name.env and copy that to the");
        Logger_1.Logger.instanse.info("cli", "", "source directory");
        return;
    }
    Logger_1.Logger.instanse.info("cli", "", "openflow-cli [--init][--install][--uninstall][--start][--stop] name");
    Logger_1.Logger.instanse.info("cli", "", "   --init - Create a sample environment file for running openflow");
    Logger_1.Logger.instanse.info("cli", "", "   --install - Install openflow as an service that runs at boot");
    Logger_1.Logger.instanse.info("cli", "", "   --uninstall - Uninstalls service, if openflow has been installed as an service");
    Logger_1.Logger.instanse.info("cli", "", "   --start - Will start the service with the given name");
    Logger_1.Logger.instanse.info("cli", "", "   --stop - Will stop the service with the given name");
    Logger_1.Logger.instanse.info("cli", "", "   name - Service and instance name");
    Logger_1.Logger.instanse.info("cli", "", "Will look for an envoriment file called name.env and copy that to the");
    Logger_1.Logger.instanse.info("cli", "", "source directory");
}
doit();
// node C:\code\openflow\OpenFlowNodeRED\dist\cli.js --install noderedlocal
//# sourceMappingURL=cli.js.map