/*
 * 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 fetch = require('fetch-retry')(require('isomorphic-fetch'));
const kinds = require('./kinds/kinds');
const path = require('path');
const log = require("./log");
const Docker = require('dockerode');
const getPort = require('get-port');
const dockerUtils = require('./dockerutils');
const prettyBytes = require('pretty-bytes');

const RUNTIME_PORT = 8080;
const MAX_INIT_RETRY_MS = 20000; // 20 sec
const INIT_RETRY_DELAY_MS = 200;

// https://github.com/apache/incubator-openwhisk/blob/master/docs/reference.md#system-limits
const OPENWHISK_DEFAULTS = {
    timeout: 60*1000,
    memory: 256
};

// if value is a function, invoke it with args, otherwise return it as object
// if value is undefined, will return undefined
function resolveValue(value, ...args) {
    if (typeof value === "function") {
        return value(...args);
    } else {
        return value;
    }
}

class OpenWhiskInvoker {
    constructor(actionName, action, options, wskProps, wsk) {
        this.actionName = actionName;
        this.action = action;

        this.kind = options.kind;
        this.image = options.image;
        this.port = options.port;
        this.internalPort = options.internalPort;
        this.command = options.command;
        this.dockerArgs = options.dockerArgs;

        // the build path can be separate, if not, same as the source/watch path
        this.sourcePath = options.buildPath || options.sourcePath;
        if (this.sourcePath) {
            this.sourceDir = process.cwd();
            // ensure sourcePath is relative to sourceDir
            this.sourceFile = path.relative(this.sourceDir, this.sourcePath);
        }

        this.main = options.main;

        this.wskProps = wskProps;
        this.wsk = wsk;

        this.containerName = dockerUtils.safeContainerName(`wskdebug-${this.action.name}-${Date.now()}`);
        this.docker = new Docker();
    }

    async checkIfDockerAvailable() {
        try {
            await this.docker.ping();
            log.debug("docker - availability check")
        } catch (e) {
            throw new Error("Docker not running on local system. A local docker environment is required for the debugger.")
        }
    }

    async getImageForKind(kind) {
        try {
            const owSystemInfo = await this.wsk.actions.client.request("GET", "/");
            if (owSystemInfo.runtimes) {
                // transform result into a nice dictionary kind => image
                const runtimes = {};
                for (const set of Object.values(owSystemInfo.runtimes)) {
                    for (const entry of set) {
                        let image = entry.image;
                        // fix for Adobe I/O Runtime reporting incorrect image prefixes
                        image = image.replace("bladerunner/", "adobeapiplatform/");
                        runtimes[entry.kind] = image;
                    }
                }
                return runtimes[kind];

            } else {
                log.warn("Could not retrieve runtime images from OpenWhisk, using default image list.");
            }

        } catch (e) {
            log.warn("Could not retrieve runtime images from OpenWhisk, using default image list.", e.message);
        }
        return kinds.images[kind];
    }

    async prepare() {
        const action = this.action;

        // this must run after initial build was kicked off in Debugger so that built files are present

        // kind and image - precendence:
        // 1. arguments (this.image)
        // 2. action (action.exec.image)
        // 3. defaults (kinds.images[kind])

        const kind = this.kind || action.exec.kind;

        if (kind === "blackbox") {
            throw new Error("Action is of kind 'blackbox', must specify kind using `--kind` argument.");
        }

        this.image = this.image || action.exec.image || await this.getImageForKind(kind);

        if (!this.image) {
            throw new Error(`Unknown kind: ${kind}. You might want to specify --image.`);
        }

        // debugging instructions
        this.debugKind = kinds.debugKinds[kind] || kind.split(":")[0];
        try {
            this.debug = require(`${__dirname}/kinds/${this.debugKind}/${this.debugKind}`);
        } catch (e) {
            log.warn(`Cannot find debug info for kind ${this.debugKind}:`, e.message);
            this.debug = {};
        }

        this.debug.internalPort = this.internalPort                      || resolveValue(this.debug.port, this);
        this.debug.port         = this.port         || this.internalPort || resolveValue(this.debug.port, this);

        // ------------------------

        this.debug.command = this.command || resolveValue(this.debug.command, this);

        if (!this.debug.port) {
            throw new Error(`No debug port known for kind: ${kind}. Please specify --port.`);
        }
        if (!this.debug.internalPort) {
            throw new Error(`No debug port known for kind: ${kind}. Please specify --internal-port.`);
        }
        if (!this.debug.command) {
            throw new Error(`No debug command known for kind: ${kind}. Please specify --command.`);
        }

        // limits
        this.memory = (action.limits.memory || OPENWHISK_DEFAULTS.memory) * 1024 * 1024;

        // source mounting
        if (this.sourcePath) {
            if (!this.debug.mountAction) {
                log.warn(`Warning: Sorry, mounting sources not yet supported for: ${kind}.`);
                this.sourcePath = undefined;
            }
        }

        this.dockerArgsFromKind = resolveValue(this.debug.dockerArgs, this) || "";
        this.dockerArgsFromUser = this.dockerArgs || "";

        if (this.sourcePath && this.debug.mountAction) {
            this.sourceMountAction = resolveValue(this.debug.mountAction, this);
        }
    }

    async isImagePresent(image, debug) {
        try {
            await this.docker.getImage(image).inspect();
            debug(`docker - image inspected, is present: ${image}`);
            return true;
        } catch (e) {
            debug(`docker - image inspected, not found: ${image}`);
            return false;
        }
    }

    async pull(image) {
        await new Promise((resolve, reject) => {
            this.docker.pull(image, (err, stream) => {
                // streaming output from pull...
                if (err) {
                    return reject(err);
                }

                function onFinished(err, output) {
                    if (err) {
                        return reject(err);
                    }
                    return resolve(output);
                }

                const events = {};
                function onProgress(event) {
                    if (!event.progress) {
                        return;
                    }

                    if (event.status) {
                        events[event.status] = events[event.status] || {};
                        if (event.id) {
                            events[event.status][event.id] = event;
                        }
                    }
                    const progressMsg = Object.entries(events).reduce((result, [status, events], idx) => {
                        const progress = Object.values(events).reduce((sum, e) => {
                            if (e.progressDetail && e.progressDetail.current && e.progressDetail.total) {
                                sum.current += e.progressDetail.current;
                                sum.total   += e.progressDetail.total;
                            }
                            return sum;
                        }, { current: 0, total: 0 });

                        return result + `${idx > 0 ? ", " : ""}${status}: ${prettyBytes(progress.current)} of ${prettyBytes(progress.total)}`;
                    }, "");

                    log.spinner(`Pulling docker image ${image} (${progressMsg})`);
                }

                this.docker.modem.followProgress(stream, onFinished, onProgress);
            });
        });
    }

    async startContainer(debug) {
        if (!await this.isImagePresent(this.image, debug)) {
            // show after 8 seconds, as VS code will timeout after 10 secs by default,
            // so that the user can see it after all the "docker pull" progress output
            setTimeout(() => {
                log.warn(`
+------------------------------------------------------------------------------------------+
| Docker image being downloaded: ${this.image}
|                                                                                          |
| Note: If you debug in VS Code and it fails with "Cannot connect to runtime process"      |
| due to a timeout, run this command once:                                                 |
|                                                                                          |
|     docker pull ${this.image}
|                                                                                          |
| Alternatively set a higher 'timeout' in the launch configuration, such as 60000 (1 min). |
+------------------------------------------------------------------------------------------+
`);
            }, 8000);

            debug(`Pulling ${this.image}`)
            log.spinner(`Pulling ${this.image}...`);

            await this.pull(this.image);

            debug("Pull complete");
        }

        log.spinner('Starting container');

        // links for docker create container config:
        //   docker api: https://docs.docker.com/engine/api/v1.37/#operation/ContainerCreate
        //   docker run impl: https://github.com/docker/cli/blob/2c3797015f5e7ef4502235b638d161279c471a8d/cli/command/container/run.go#L33
        //   https://github.com/apocas/dockerode/issues/257
        //   https://github.com/apocas/dockerode/blob/master/lib/docker.js#L1442
        //   https://medium.com/@johnnyeric/how-to-reproduce-command-docker-run-via-docker-remote-api-with-node-js-5918d7b221ea

        const containerRuntimePort = `${RUNTIME_PORT}/tcp`;
        const hostRuntimePort = await getPort();
        this.containerURL = `http://0.0.0.0:${hostRuntimePort}`;
        const containerDebugPort = `${this.debug.internalPort}/tcp`;

        const createContainerConfig = {
            name: this.containerName,
            Image: this.image,
            Cmd: [ 'sh', '-c', this.debug.command ],
            Env: [],
            Volumes: {},
            ExposedPorts: {
                [containerRuntimePort]: {},
                [containerDebugPort]: {}
            },
            HostConfig: {
                AutoRemove: true,
                PortBindings: {
                    [containerRuntimePort]: [{ HostPort: `${hostRuntimePort}` }],
                    [containerDebugPort]: [{ HostPort: `${this.debug.port}` }]
                },
                Memory: this.memory,
                Binds: []
            }
        };

        if (this.debug.updateContainerConfig) {
            this.debug.updateContainerConfig(this, createContainerConfig);
        }

        dockerUtils.dockerRunArgs2CreateContainerConfig(this.dockerArgsFromUser, createContainerConfig);

        debug("docker - creating container:", createContainerConfig);

        this.container = await this.docker.createContainer(createContainerConfig);

        const stream = await this.container.attach({
            stream: true,
            stdout: true,
            stderr: true
        });

        const spinnerSafeStream = (stream) => ({
            write: (data) => {
                log.stopSpinner();
                stream(data.toString().replace(/\n$/, ""));
                log.resumeSpinner();
            }
        });

        this.container.modem.demuxStream(
            stream,
            spinnerSafeStream(console.log),
            spinnerSafeStream(console.error)
        );

        await this.container.start();

        debug(`docker - started container ${this.container.id}`);
    }

    getSourcePath() {
        return this.sourcePath;
    }

    getImage() {
        return this.image;
    }

    getDebugKind() {
        return this.debugKind;
    }

    getPort() {
        return this.debug.port;
    }

    name() {
        return this.containerName;
    }

    url() {
        return this.containerURL || "";
    }

    timeout() {
        return this.action.limits.timeout || OPENWHISK_DEFAULTS.timeout;
    }

    async init(actionWithCode) {
        let action;
        if (this.sourceMountAction) {
            action = this.sourceMountAction;

        } else {
            action = {
                binary: actionWithCode.exec.binary,
                main:   actionWithCode.exec.main || "main",
                code:   actionWithCode.exec.code,
            };
        }

        const RETRIES = MAX_INIT_RETRY_MS / INIT_RETRY_DELAY_MS;

        const response = await fetch(`${this.url()}/init`, {
            method: "POST",
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                value: action
            }),
            retryDelay: INIT_RETRY_DELAY_MS,
            retryOn: function(attempt, error) {
                // after 1.5 seconds, show retry to user via spinner
                if (attempt >= 1500 / INIT_RETRY_DELAY_MS) {
                    log.spinner(`Installing action (retry ${attempt}/${RETRIES})`)
                }
                return error !== null && attempt < RETRIES;
            }
        });

        if (response.status === 502) {
            const body = await response.json();
            throw new Error("Could not initialize action code on local debug container:\n\n" + body.error);
        }
    }

    async run(args, activationId) {
        const response = await fetch(`${this.url()}/run`, {
            method: "POST",
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                value: args,

                api_host        : this.wskProps.apihost,
                api_key         : this.wskProps.api_key,
                namespace       : this.wskProps.namespace,
                action_name     : `/${this.wskProps.namespace}/${this.actionName}`,
                activation_id   : activationId,
                deadline        : `${Date.now() + this.timeout()}`,
                allow_concurrent: "true"
            })
        });

        return response.json();
    }

    async stop() {
        if (this.container) {
            // log this here for VS Code, will be the last visible log message since
            // we will be killed by VS code after the container is gone after the kill()
            log.log(`Stopping container ${this.name()}.`);
            await this.container.kill();
            delete this.container;
            log.debug(`docker - stopped container ${this.name()}`);
        }
    }
}

module.exports = OpenWhiskInvoker;
