/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

'use strict';

const yargs = require("yargs");
const Debugger = require("./src/debugger");
const path = require("path");
const fs = require("fs");

function enableConsoleColors() {
    // colorful console.error() and co
    let originalConsole = null;
    if (!console._logToFile) {
        originalConsole = {
            log: console.log,
            error: console.error,
            info: console.info,
            debug: console.debug
        };
        // overwrites console.log and co
        require('manakin').global;
    }
    return originalConsole;
}

function resetConsoleColors(originalConsole) {
    if (originalConsole) {
        console.log = originalConsole.log;
        console.error = originalConsole.error;
        console.info = originalConsole.info;
        console.debug = originalConsole.debug;
    }
}

function getSupportedKinds() {
    const kinds = [];
    const basePath = path.resolve(__dirname, "src/kinds");
    fs.readdirSync(basePath).forEach(function(entry) {
        const p = path.resolve(basePath, entry);
        if (fs.statSync(p).isDirectory()) {
            const kind = require(path.resolve(p, entry));
            kinds.push(`${entry}: ${kind.description}`);
        }
    });
    return kinds;
}

function yargsOptions(yargs) {
    yargs.positional('action', {
        describe: 'Name of action to debug',
        type: 'string'
    });
    yargs.positional('source-path', {
        describe: 'Path to local action sources, file or folder (optional)',
        type: 'string'
    });

    // action options
    yargs.option("m", {
        alias: "main",
        type: "string",
        group: "Action options:",
        describe: "Name of action entry point"
    });
    yargs.option("k", {
        alias: "kind",
        type: "string",
        group: "Action options:",
        describe: "Action kind override, needed for blackbox images"
    });
    yargs.option("i", {
        alias: "image",
        type: "string",
        group: "Action options:",
        describe: "Docker image to use as action container"
    });
    yargs.option("on-build", {
        type: "string",
        group: "Action options:",
        describe: "Shell command for custom action build step"
    });
    yargs.option("build-path", {
        type: "string",
        group: "Action options:",
        describe: "Path to built action, result of --on-build command"
    });

    // source watching
    yargs.option("l", {
        type: "boolean",
        implies: "source-path",
        group: "LiveReload options:",
        describe: "Enable browser LiveReload on [source-path]"
    });
    yargs.option("lr-port", {
        type: "number",
        implies: "l",
        group: "LiveReload options:",
        describe: "Port for browser LiveReload (defaults to 35729)"
    });
    yargs.option("P", {
        type: "string",
        group: "LiveReload options:",
        describe: "Invoke action with these parameters on changes to [source-path].\nArgument can be json string or name of json file."
    });
    yargs.option("a", {
        type: "string",
        group: "LiveReload options:",
        describe: "Name of custom action to invoke upon changes to [source-path].\nDefaults to <action> if -P is set."
    });
    yargs.option("r", {
        type: "string",
        group: "LiveReload options:",
        describe: "Shell command to run upon changes to [source-path]"
    });
    yargs.option("watch", {
        type: "string",
        array: true,
        group: "LiveReload options:",
        describe: "Glob pattern(s) to watch for source modifications"
    });
    yargs.option("watch-exts", {
        type: "string",
        array: true,
        group: "LiveReload options:",
        describe: "File extensions to watch for modifications"
    });

    // Debugger options
    yargs.option("p", {
        alias: "port",
        type: "number",
        group: "Debugger options:",
        describe: "Debug port exposed from container that debugging clients connect to. Defaults to --internal-port if set or standard debug port of the kind. Node.js arguments --inspect and co. can be used too."
    });
    yargs.option("internal-port", {
        type: "number",
        group: "Debugger options:",
        describe: "Actual debug port inside the container. Must match port opened by --command. Defaults to standard debug port of kind."
    });
    yargs.option("command", {
        type: "string",
        group: "Debugger options:",
        describe: "Custom container command that enables debugging"
    });
    yargs.option("docker-args", {
        type: "string",
        group: "Debugger options:",
        describe: "Additional docker run arguments for container. Must be quoted and start with space: 'wskdebug --docker-args \" -e key=var\" myaction'"
    });
    yargs.option("on-start", {
        type: "string",
        group: "Debugger options:",
        describe: "Shell command to run when debugger is up"
    });

    // Agent options
    yargs.option("c", {
        alias: "condition",
        type: "string",
        group: "Agent options:",
        describe: "Hit condition to trigger debugger. Javascript expression evaluated against input parameters. Example: 'debug == 'true'"
    });
    yargs.option("agent-timeout", {
        type: "number",
        group: "Agent options:",
        describe: "Debugging agent timeout (seconds). Default: 5 min"
    });
    yargs.option("ngrok", {
        type: "boolean",
        group: "Agent options:",
        describe: "Use 3rd party service ngrok.com for agent forwarding."
    });
    yargs.option("ngrok-region", {
        type: "string",
        group: "Agent options:",
        describe: "Ngrok region to use. Defaults to 'us'."
    });

    // nodejs options
    yargs.option("inspect", {
        alias: ["inspect-brk", "inspect-port", "debug", "debug-brk", "debug-port"],
        hidden: true,
        type: "number"
    });

    // general options
    yargs.option("v", {
        alias: "verbose",
        type: "boolean",
        describe: "Verbose output. Logs activation parameters and result"
    });
    yargs.version(require("./package.json").version);
}

function getYargsParser() {
    return yargs
        .help()
        .alias("h", "help")
        .updateStrings({
            'Positionals:': 'Arguments:',
            'Not enough non-option arguments: got %s, need at least %s': {
                "one": "Error: Missing argument <action> (%s/%s)",
                "other": "Error: Missing argument <action> (%s/%s)"
            }
        })
        .version(false)
        .wrap(90)
        .command(
            "* <action> [source-path]",
            // eslint-disable-next-line indent
           `.            ____      ___                   _    _ _     _     _
            .           /\\   \\    / _ \\ _ __   ___ _ __ | |  | | |__ (_)___| | __
            .      /\\  /__\\   \\  | | | | '_ \\ / _ \\ '_ \\| |  | | '_ \\| / __| |/ /
            .     /  \\____ \\  /  | |_| | |_) |  __/ | | | |/\\| | | | | \\__ \\   <
            .     \\   \\  /  \\/    \\___/| .__/ \\___|_| |_|__/\\__|_| |_|_|___/_|\\_\\
            .      \\___\\/ tm           |_|

            .                              W S K D E B U G

            Debug an Apache OpenWhisk <action> by forwarding its activations to a local docker
            container that has debugging enabled and its debug port exposed to the host.

            If only <action> is specified, the deployed action code is debugged.

            If [source-path] is set, it must point to the local action sources which will be mounted
            into the debug container. Sources will be automatically reloaded on each new activation.
            This feature depends on the kind.

            Supported kinds:
            - ${getSupportedKinds().join("\n")}
            `,
            yargsOptions
        );
}

function normalizeArgs(argv) {
    // pass hidden node.js arg aliases to port option
    argv.port = argv.inspect || argv.p;
    // more readable internal argument names
    argv.livereload = argv.l;
    argv.livereloadPort = argv.lrPort;
    argv.invokeParams = argv.P;
    argv.invokeAction = argv.a;
    argv.onChange = argv.r;
}

function printErrorAndExit(err, argv) {
    console.log();
    if (argv.verbose) {
        console.error(err);
    } else {
        console.error("Error:", err.message);
    }
    process.exit(1);
}

function registerExitHandler(dbg) {
    // ensure we remove the agent when this app gets terminated
    ['SIGINT', 'SIGTERM'].forEach(signal => {
        process.on(signal, async () => {
            await dbg.kill();

            process.exit();
        });
    });
}

async function wskdebug(args, isCommandLine=false) {
    const originalConsole = enableConsoleColors();

    try {
        const parser = getYargsParser();

        // if cli mode, we want to exit the process, otherwise throw an error
        parser.showHelpOnFail(isCommandLine);
        parser.exitProcess(isCommandLine);

        const argv = parser.parse(args);
        normalizeArgs(argv);

        if (argv.help || argv.version) {
            // do nothing
            return;
        }

        try {
            const dbg = new Debugger(argv);
            if (isCommandLine) {
                registerExitHandler(dbg);
            }
            await dbg.start();
            await dbg.run();

        } catch (e) {
            if (isCommandLine) {
                printErrorAndExit(e, argv);
            } else {
                throw e;
            }
        }

    } finally {
        resetConsoleColors(originalConsole);
    }
}

// exporting the resulting promise for unit tests
module.exports = wskdebug;
