/*
 * 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 debug = require('./debug');
const prettyBytes = require('pretty-bytes');
const prettyMilliseconds = require('pretty-ms');

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

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

        this.wskProps = wskprops.get();
        if (Object.keys(this.wskProps).length === 0) {
            console.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) {
            console.error(`Error: Could not setup openwhisk client: ${err.message}`);
            process.exit(1);
        }
    }

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

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

        this.wskProps.namespace = actionMetadata.namespace;
        console.info(`Starting debugger for /${this.wskProps.namespace}/${this.actionName}`);

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

        try {
            // run build initially (would be required by starting container)
            if (this.argv.onBuild) {
                console.info("=> 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 debugTask = debug.task();

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

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

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

                debugTask(`got 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];

            // parallelize slower work using promises again

            // task 3 - initialize local container with code
            const initTask = (async () => {
                const debugTask = debug.task();

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

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

            // task 4 - install agent in openwhisk
            const agentTask = (async () => {
                const debugTask = debug.task();

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

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

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

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

            console.log();
            console.info(`Action     : /${this.wskProps.namespace}/${this.actionName}`);
            if (this.sourcePath) {
                console.info(`Sources    : ${this.invoker.getSourcePath()}`);
            }
            console.info(`Image      : ${this.invoker.getImage()}`);
            console.info(`OpenWhisk  : ${this.wskProps.apihost}`);
            console.info(`Container  : ${this.invoker.name()}`);
            console.info(`Debug type : ${this.invoker.getDebugKind()}`);
            console.info(`Debug port : localhost:${this.invoker.getPort()}`);
            if (this.argv.condition) {
                console.info(`Condition  : ${this.argv.condition}`);
            }
            console.log();
            console.info(`Ready for activations. Started in ${prettyMilliseconds(Date.now() - this.startTime)}. Use CTRL+C to exit`);

            this.ready = true;

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

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

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

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

                    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.shuttingDown) {
            return;
        }
        this.shuttingDown = true;
        const shutdownStart = Date.now();
        debug("shutting down...");

        // only log this if we started properly
        if (this.ready) {
            console.log();
            console.log();
            console.log("Shutting down...");
        }

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

        if (this.agentMgr) {
            await this.tryCatch(this.agentMgr.shutdown());
        }
        if (this.invoker) {
            await this.tryCatch(this.invoker.stop());
            debug(`stopped container: ${this.invoker.name()}`);
        }
        if (this.watcher) {
            await this.tryCatch(this.watcher.stop());
            debug("stopped source file watching");
        }

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

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

    async tryCatch(task, message="Error during shutdown:") {
        try {
            if (typeof task === "function") {
                task();
            } else {
                await task;
            }
        } catch (e) {
            console.log(e);
            if (this.argv.verbose) {
                console.error(message);
                console.error(e);
            } else {
                console.error(message, e.message);
            }
        }
    }

}

module.exports = Debugger;
