/*
 * 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 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.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;
