/*
 * 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 wskprops = require('./wskprops');
const OpenWhiskInvoker = require('./invoker');
const AgentMgr = require('./agentmgr');
const Watcher = require('./watcher');
const openwhisk = require('openwhisk');
const { spawnSync } = require('child_process');
const sleep = require('util').promisify(setTimeout);
const prettyBytes = require('pretty-bytes');
const prettyMilliseconds = require('pretty-ms');
const log = require('./log');

function prettyMBytes1024(mb) {
    if (mb > 1024) {
        return `${mb/1024} GB`;
    } else {
        return `${mb} MB`;
    }
}

function getNamespaceFromActionMetadata(actionMetadata) {
    // if the action is inside a package, this returns <namespace>/<package>
    // but we only want the namespace
    return actionMetadata.namespace.split("/")[0];
}

/**
 * Central component of wskdebug.
 */
class Debugger {
    constructor(argv) {
        this.startTime = Date.now();
        log.debug("starting debugger");

        this.argv = argv;
        this.actionName = argv.action;

        this.wskProps = wskprops.get();
        if (Object.keys(this.wskProps).length === 0) {
            log.error(`Error: Missing openwhisk credentials. Found no ~/.wskprops or .env file or WSK_* environment variable.`);
            process.exit(1);
        }
        if (argv.ignoreCerts) {
            this.wskProps.ignore_certs = true;
        }

        try {
            this.wsk = openwhisk(this.wskProps);
        } catch (err) {
            log.error(`Error: Could not setup openwhisk client: ${err.message}`);
            process.exit(1);
        }

        const h = log.highlightColor;
        log.spinner("Debugging " + h(`/_/${this.actionName}`) + " on " + h(this.wskProps.apihost));
    }

    async start() {
        this.agentMgr = new AgentMgr(this.argv, this.wsk, this.actionName);
        this.watcher = new Watcher(this.argv, this.wsk);

        // get the action metadata
        this.actionMetadata = await this.agentMgr.peekAction();
        log.debug("fetched action metadata from openwhisk");
        this.wskProps.namespace = getNamespaceFromActionMetadata(this.actionMetadata);

        const h = log.highlightColor;
        log.step("Debugging " + h(`/${this.wskProps.namespace}/${this.actionName}`) + " on " + h(this.wskProps.apihost));

        // local debug container
        this.invoker = new OpenWhiskInvoker(this.actionName, this.actionMetadata, this.argv, this.wskProps, this.wsk);

        // quick fail for missing requirements such as docker not running
        await this.invoker.checkIfDockerAvailable();

        try {
            // run build initially (would be required by starting container)
            if (this.argv.onBuild) {
                log.highlight("On build: ", this.argv.onBuild);
                spawnSync(this.argv.onBuild, {shell: true, stdio: "inherit"});
            }
            await this.invoker.prepare();

            // parallelize slower work using promises

            // task 1 - start local container
            const containerTask = (async () => {
                const debug2 = log.newDebug();

                // start container - get it up fast for VSCode to connect within its 10 seconds timeout
                await this.invoker.startContainer(debug2);

                debug2(`started container: ${this.invoker.name()}`);
            })();

            // task 2 - fetch action code from openwhisk
            const openwhiskTask = (async () => {
                const debug2 = log.newDebug();
                const actionWithCode = await this.agentMgr.readActionWithCode();

                debug2(`downloaded action code (${prettyBytes(actionWithCode.exec.code.length)})`);
                return actionWithCode;
            })();

            // wait for both tasks 1 & 2
            const results = await Promise.all([containerTask, openwhiskTask]);
            const actionWithCode = results[1];

            log.spinner('Installing agent');

            // parallelize slower work using promises again

            // task 3 - initialize local container with code
            const initTask = (async () => {
                const debug2 = log.newDebug();

                // /init local container
                await this.invoker.init(actionWithCode);

                debug2("installed action on container");
            })();

            // task 4 - install agent in openwhisk
            const agentTask = (async () => {
                const debug2 = log.newDebug();

                // setup agent in openwhisk
                await this.agentMgr.installAgent(this.invoker, debug2);
            })();

            await Promise.all([initTask, agentTask]);

            if (this.argv.onStart) {
                log.highlight("On start: ", this.argv.onStart);
                spawnSync(this.argv.onStart, {shell: true, stdio: "inherit"});
            }

            // start source watching (live reload) if requested
            await this.watcher.start();

            this.logDetails();
            const abortMsg = log.isInteractive ? log.highlightColor(" Use CTRL+C to exit.") : "";
            log.ready(`Ready for activations. Started in ${prettyMilliseconds(Date.now() - this.startTime)}.${abortMsg}`);

            this.ready = true;

        } catch (e) {
            await this.shutdown();
            throw e;
        }
    }

    async logDetails() {
        log.stopSpinner();
        log.log();
        log.highlight("Action     : ", `/${this.wskProps.namespace}/${this.actionName}`);
        if (this.sourcePath) {
            log.highlight("Sources    : ", `${this.invoker.getSourcePath()}`);
        }
        log.highlight("Image      : ", `${this.invoker.getImage()}`);
        log.highlight("Container  : ", `${this.invoker.name()}`);
        if (this.actionMetadata.limits) {
            if (this.actionMetadata.limits.memory) {
                log.highlight("Memory     : ", `${prettyMBytes1024(this.actionMetadata.limits.memory)}`);
            }
            if (this.actionMetadata.limits.timeout) {
                log.highlight("Timeout    : ", `${prettyMilliseconds(this.actionMetadata.limits.timeout, {verbose:true})}`);
            }
        }
        log.highlight("Debug type : ", `${this.invoker.getDebugKind()}`);
        log.highlight("Debug port : ", `localhost:${this.invoker.getPort()}`);
        if (this.argv.condition) {
            log.highlight("Condition  : ", `${this.argv.condition}`);
        }
        log.log();
    }

    async run() {
        return this.runPromise = this._run();
    }

    async _run() {
        try {
            this.running = true;

            // main blocking loop
            // abort if this.running is set to false
            // from here on, user can end debugger with ctrl+c
            while (this.running) {
                if (this.argv.ngrok) {
                    // agent: ngrok
                    // simply block, ngrokServer keeps running in background
                    await sleep(1000);

                } else {
                    // agent: concurrent
                    // agent: non-concurrent
                    // wait for activation, run it, complete, repeat
                    const activation = await this.agentMgr.waitForActivations();
                    if (!activation) {
                        return;
                    }

                    const id = activation.$activationId;
                    delete activation.$activationId;
                    log.verbose("Parameters:", activation);

                    const startTime = Date.now();

                    // run this activation on the local docker container
                    // which will block if the actual debugger hits a breakpoint
                    const result = await this.invoker.run(activation, id);

                    const duration = Date.now() - startTime;

                    // pass on the local result to the agent in openwhisk
                    if (!await this.agentMgr.completeActivation(id, result, duration)) {
                        return;
                    }
                }
            }
        } finally {
            await this.shutdown();
        }
    }

    // normal graceful stop() initiated by a client
    async stop() {
        this.running = false;
        if (this.agentMgr) {
            this.agentMgr.stop();
        }

        if (this.runPromise) {
            // wait for the main loop to gracefully end, which will call shutdown()
            await this.runPromise;
        } else {
            // someone called stop() without run()
            await this.shutdown();
        }
    }

    // fastest way to end, triggered by CTRL+C
    async kill() {
        this.running = false;
        if (this.agentMgr) {
            this.agentMgr.stop();
        }

        await this.shutdown();
    }

    async shutdown() {
        // avoid duplicate shutdown on CTRL+C
        if (!this.shutdownPromise) {
            this.shutdownPromise = this._shutdown();
        }

        await this.shutdownPromise;
        delete this.shutdownPromise;
    }

    async _shutdown() {
        const shutdownStart = Date.now();

        // only log this if we started properly
        if (this.ready) {
            log.log();
            log.log();
            log.debug("shutting down...");
        } else {
            log.debug("aborting start - shutting down ...");
        }
        log.spinner("Shutting down");

        // need to shutdown everything even if some fail, hence tryCatch() for each

        if (this.agentMgr) {
            await this.tryCatch(this.agentMgr.shutdown());
        }

        // ------------< critical removal must happen above this line >---------------

        // in VS Code, we will not run beyond this line upon debug stop.
        // this is because invoker.stop() will kill the container & thus close the
        // debug port, upon which VS Code kills the debug process (us)
        if (this.invoker) {
            await this.tryCatch(this.invoker.stop());
        }

        if (this.watcher) {
            // this is not critical on a process exit, only if Debugger is used programmatically
            // and might be reused for a new run()
            await this.tryCatch(this.watcher.stop());
            log.debug("stopped source file watching");
        }

        // only log this if we started properly
        if (this.ready) {
            log.succeed(`Done. Shutdown in ${prettyMilliseconds(Date.now() - shutdownStart)}.`);
        }
        this.ready = false;
    }

    // ------------------------------------------------< utils >-----------------

    async tryCatch(task) {
        try {
            if (typeof task === "function") {
                task();
            } else {
                await task;
            }
        } catch (e) {
            log.exception(e, "Error during shutdown:");
        }
    }

}

module.exports = Debugger;
