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

/**
 * Object which encapsulates a first-class function, the user code for an action.
 *
 * This file (runner.js) must currently live in root directory for nodeJsAction.
 */
const fs = require('fs');
const path = require('path');

/** Initializes the handler for the user function. */
function initializeActionHandler(message) {
    if (message.binary) {
        // The code is a base64-encoded zip file.
        return unzipInTmpDir(message.code)
            .then(moduleDir => {
                let parts = splitMainHandler(message.main);
                if (parts === undefined) {
                    // message.main is guaranteed to not be empty but be defensive anyway
                    return Promise.reject('Name of main function is not valid.');
                }

                // If there is only one property in the "main" handler, it is the function name
                // and the module name is specified either from package.json or assumed to be index.js.
                let [index, main] = parts;

                // Set the executable directory to the project dir.
                process.chdir(moduleDir);

                if (index === undefined && !fs.existsSync('package.json') && !fs.existsSync('index.js')) {
                    return Promise.reject('Zipped actions must contain either package.json or index.js at the root.');
                }

                //  The module to require.
                let whatToRequire = index !== undefined ? path.join(moduleDir, index) : moduleDir;
                let handler = eval('require("' + whatToRequire + '").' + main);
                return assertMainIsFunction(handler, message.main);
            })
            .catch(error => Promise.reject(error));
    } else try {
        // The code is a plain old JS file.
        let handler = eval('(function(){' + message.code + '\nreturn ' + message.main + '})()');
        return assertMainIsFunction(handler, message.main);
    } catch (e) {
        return Promise.reject(e);
    }
}

class NodeActionRunner {

    constructor(handler) {
        this.userScriptMain = handler;
    }

    run(args) {
        return new Promise((resolve, reject) => {
            try {
                var result = this.userScriptMain(args);
            } catch (e) {
                reject(e);
            }

            this.finalizeResult(result, resolve);
        });
    };

    finalizeResult(result, resolve) {
        // Non-promises/undefined instantly resolve.
        Promise.resolve(result).then(resolvedResult => {
            // This happens, e.g. if you just have "return;"
            if (typeof resolvedResult === "undefined") {
                resolvedResult = {};
            }
            resolve(resolvedResult);
        }).catch(error => {
            // A rejected Promise from the user code maps into a
            // successful promise wrapping a whisk-encoded error.

            // Special case if the user just called "reject()".
            if (!error) {
                resolve({error: {}});
            } else {
                const serializeError = require('serialize-error');
                resolve({error: serializeError(error)});
            }
        });
    }
}

/**
 * Copies the base64 encoded zip file contents to a temporary location,
 * decompresses it and returns the name of that directory.
 *
 * Note that this makes heavy use of shell commands because the environment is expected
 * to provide the required executables.
 */
function unzipInTmpDir(zipFileContents) {
    const mkTempCmd = "mktemp -d XXXXXXXX";
    return exec(mkTempCmd).then(tmpDir => {
        return new Promise((resolve, reject) => {
            const zipFile = path.join(tmpDir, "action.zip");
            fs.writeFile(zipFile, zipFileContents, "base64", err => {
                if (!err) resolve(zipFile);
                else reject("There was an error reading the action archive.");
            });
        });
    }).then(zipFile => {
        return exec(mkTempCmd).then(tmpDir => {
            return exec("unzip -qq " + zipFile + " -d " + tmpDir)
                .then(res => path.resolve(tmpDir))
                .catch(error => Promise.reject("There was an error uncompressing the action archive."));
        });
    });
}

/** Helper function to run shell commands. */
function exec(cmd) {
    const child_process = require('child_process');

    return new Promise((resolve, reject) => {
        child_process.exec(cmd, (error, stdout, stderr) => {
            if (!error) {
                resolve(stdout.trim());
            } else {
                reject(stderr.trim());
            }
        });
    });
}

/**
 * Splits handler into module name and path to main.
 * If the string contains no '.', return [ undefined, the string ].
 * If the string contains one or more '.', return [ string up to first period, rest of the string after ].
 */
function splitMainHandler(handler) {
    let matches = handler.match(/^([^.]+)$|^([^.]+)\.(.+)$/);
    if (matches && matches.length == 4) {
        let index = matches[2];
        let main = matches[3] || matches[1];
        return [index, main]
    } else return undefined
}

function assertMainIsFunction(handler, name) {
    if (typeof handler === 'function') {
        return Promise.resolve(handler);
    } else {
        return Promise.reject("Action entrypoint '" + name + "' is not a function.");
    }
}

module.exports = {
    NodeActionRunner,
    initializeActionHandler
};
