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

var dbg = require('../utils/debug');
var DEBUG = new dbg();

const OW_ENV_PREFIX = "__OW_";

/**
 * Pre-process the incoming
 */
function preProcessInitData(env, initdata, valuedata, activationdata) {
    DEBUG.functionStart();
    try {
        // Set defaults to use INIT data not provided on the request
        // Look first to the process (i.e., Container's) environment variables.
        var main = (typeof env.__OW_ACTION_MAIN === 'undefined') ? "main" : env.__OW_ACTION_MAIN;
        // TODO: Throw error if CODE is NOT defined!
        var code = (typeof env.__OW_ACTION_CODE === 'undefined') ? "" : env.__OW_ACTION_CODE;
        var binary = (typeof env.__OW_ACTION_BINARY === 'undefined') ? false : env.__OW_ACTION_BINARY.toLowerCase() === "true";
        // TODO: deault to empty?
        var actionName = (typeof env.__OW_ACTION_NAME === 'undefined') ? "" : env.__OW_ACTION_NAME;
        DEBUG.dumpObject(actionName, "Action name");
        DEBUG.dumpObject(main, "Action main");
        DEBUG.dumpObject(code, "Action code");
        DEBUG.dumpObject(binary, "Action binary");

        // Look for init data within the request (i.e., "stem cell" runtime, where code is injected by request)
        if (typeof(initdata) !== "undefined") {
            if (initdata.name && typeof initdata.name === 'string') {
                // TODO: Throw error if BINARY is not 'true' or 'false'
                actionName = initdata.name;
            }
            if (initdata.main && typeof initdata.main === 'string') {
                main = initdata.main
            }
            if (initdata.code && typeof initdata.code === 'string') {
                code = initdata.code
            }
            if (initdata.binary && typeof initdata.binary === 'boolean') {
                // TODO: Throw error if BINARY is not 'true' or 'false'
                binary = initdata.binary
            }
        }

        // Move the init data to the request body under the "value" key.
        // This will allow us to reuse the "openwhisk" /init route handler function
        valuedata.main = main;
        valuedata.code = code;
        valuedata.binary = binary;

        // Action name is a special case, as we have a key collision on "name" between init. data and request
        // param. data (as they both appear within "body.value") so we must save it to its final location
        // as the default Action name as part of the activation data
        // NOTE: if action name is not present in the action data, we will set it regardless even if an empty string
        if( typeof(activationdata) !== "undefined" ) {
            if ( typeof(activationdata.action_name) === "undefined" ||
                (typeof(activationdata.action_name) === "string" && activationdata.action_name.length == 0 )){
                activationdata.action_name = actionName;
            }
        }

        DEBUG.dumpObject(valuedata.main, "valuedata.main");
        DEBUG.dumpObject(valuedata.code , "valuedata.code");
        DEBUG.dumpObject(valuedata.binary, "valuedata.binary");

    } catch(e){
        console.error(e);
        DEBUG.functionEndError(e.message);
        throw("Unable to initialize the runtime: " + e.message);
    }
    DEBUG.functionEnd();
}

/**
 * Pre-process the incoming http request data, moving it to where the
 * route handlers expect it to be for an openwhisk runtime.
 */
function preProcessActivationData(env, activationdata) {
    DEBUG.functionStart();
    try {
        // Note: we move the values here so that the "run()" handler does not have
        // to move them again.
        Object.keys(activationdata).forEach(
            function (k) {
                if (typeof activationdata[k] === 'string') {
                    var envVariable = OW_ENV_PREFIX + k.toUpperCase();
                    process.env[envVariable] = activationdata[k];
                    DEBUG.dumpObject(process.env[envVariable], envVariable, "preProcessActivationData");
                }
            }
        );
    } catch(e){
        console.error(e);
        DEBUG.functionEndError(e.message);
        throw("Unable to initialize the runtime: " + e.message);
    }
    DEBUG.functionEnd();
}

/**
 * helper function to set env variables for HTTP Context
 */
function httpContextEnv (key, value) {
    if (typeof value === 'string') {
        process.env[key] = value
        DEBUG.dumpObject(process.env[key], key, "HTTPContext");
    }
}

/**
 * Pre-process HTTP request details, send them as parameters to the action input argument
 * __ow_method, __ow_headers, __ow_path, __ow_user, __ow_body, and __ow_query
 */
function preProcessHTTPContext(req) {
    DEBUG.functionStart()

    try {
        httpContextEnv(OW_ENV_PREFIX + "METHOD", req.method)
        httpContextEnv(OW_ENV_PREFIX + "HEADERS", JSON.stringify(req.headers))
        httpContextEnv(OW_ENV_PREFIX + "PATH", "");

        var namespace = "";
        if (process.env[OW_ENV_PREFIX + "NAMESPACE"] !== undefined) {
            namespace = process.env[OW_ENV_PREFIX + "NAMESPACE"];
        }
        httpContextEnv(OW_ENV_PREFIX + "USER", namespace);

        var bodyStr = JSON.stringify(req.body)
        var bodyBase64 = Buffer.from(bodyStr).toString("base64")
        httpContextEnv(OW_ENV_PREFIX + "BODY", bodyBase64)

        httpContextEnv(OW_ENV_PREFIX + "QUERY", JSON.stringify(req.query));
    } catch (e) {
        console.error(e);
        DEBUG.functionEndError(e.message);
        throw ("Unable to initialize the runtime: " + e.message)
    }
    DEBUG.functionEnd()
}


/**
 * Pre-process the incoming http request data, moving it to where the
 * route handlers expect it to be for an openwhisk runtime.
 */
function preProcessRequest(req){
    DEBUG.functionStart();

    try{
        // Get or create valid references to the various data we might encounter
        // in a request such as Init., Activation and function parameter data.
        let body = req.body || {};
        let valueData = body.value || {};
        let initData = body.init || {};
        let activationData = body.activation || {};
        let env = process.env || {};

        // process initialization (i.e., "init") data
        preProcessInitData(env, initData, valueData, activationData);

        // Fix up pointers in case we had to allocate new maps
        req.body = body;
        req.body.value = valueData;
        req.body.init = initData;
        req.body.activation = activationData;

        // process per-activation (i.e, "run") data
        preProcessActivationData(env, activationData);

        preProcessHTTPContext(req);

    } catch(e){
        console.error(e);
        DEBUG.functionEndError(e.message);
        // TODO: test this error is handled properly and results in an HTTP error response
        throw("Unable to initialize the runtime: " + e.message);
    }

    DEBUG.functionEnd();
}

function postProcessResponse(result, res) {
    DEBUG.functionStart();

    // After getting the result back from an action, update the HTTP headers,
    // status code, and body based on its result if it includes one or more of the
    // following as top level JSON properties: headers, statusCode, body
    let statusCode = result.code;
    let headers = {};
    let body = result.response;

    // statusCode: default is 200 OK if body is not empty otherwise 204 No Content
    if (result.response.statusCode !== undefined) {
        statusCode = result.response.statusCode;
        delete body['statusCode'];
    }

    // the default content-type for an HTTP response is application/json
    // this default are overwritten with the action specified headers
    if (result.response.headers !== undefined) {
        headers = result.response.headers;
        delete body['headers'];
    }

    // body: a string which is either a plain text, JSON object, or a base64 encoded string for binary data (default is "")
    // body is considered empty if it is null, "", or undefined
    if (result.response.body !== undefined) {
        body = result.response.body;
        delete body['main'];
        delete body['code'];
        delete body['binary'];
    }

    // statusCode: set it to 204 No Content if body is empty
    if (statusCode === 200 && body === "") {
        statusCode = 204;
    }

    res.header(headers).status(statusCode).json(body);

    DEBUG.functionEnd();
}


function PlatformFactory(id, svc, cfg) {

    DEBUG.dumpObject(id, "Platform" );
    DEBUG.dumpObject(svc, "Service" );
    DEBUG.dumpObject(cfg, "Config" );

    var service = svc;
    //var config = cfg;  // TODO: use this to pass future config. information uniformly to any impl.
    var isInitialized = false;

    this.run = function(req, res) {

        try {

            preProcessRequest(req);
            console.info("isInitialized="+isInitialized);

            service.initCode(req).then(function () {
                service.runCode(req).then(function (result) {
                    postProcessResponse(result, res)
                });
            }).catch(function (error) {
                console.error(error);
                if (typeof error.code === "number" && typeof error.response !== "undefined") {
                    res.status(error.code).json(error.response);
                } else {
                    console.error("[wrapEndpoint]", "invalid errored promise", JSON.stringify(error));
                    res.status(500).json({ error: "Internal error." });
                }
            });
        } catch (e) {
            res.status(500).json({error: "internal error"})
        }
    }

    var http_method = {
        get: 'GET',
        post: 'POST',
        put: 'PUT',
        delete: 'DELETE',
    };

    this.registerHandlers = function(app, platform) {
            var httpMethods = process.env.__OW_HTTP_METHODS;
            // default to "[post]" HTTP method if not defined
            if (typeof httpMethods === "undefined" || !Array.isArray(httpMethods)) {
                console.error("__OW_HTTP_METHODS is undefined; defaulting to '[post]' ...");
                httpMethods = [http_method.post];
            }
            httpMethods.forEach(function (method) {
                switch (method.toUpperCase()) {
                    case http_method.get:
                        app.get('/', platform.run);
                        break;
                    case http_method.post:
                        app.post('/', platform.run);
                        break;
                    case http_method.put:
                        app.put('/', platform.run);
                        break;
                    case http_method.delete:
                        app.delete('/', platform.run);
                        break;
                    default:
                        console.error("Environment variable '__OW_HTTP_METHODS' has an unrecognized value (" + method + ").");
                }
            });
    }
};

module.exports = PlatformFactory;
