/*
 * 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 assert = require('assert');
const nock = require('nock');
const fs = require('fs');
const { execSync } = require('child_process');
const path = require('path');
const getPort = require('get-port');

const FAKE_OPENWHISK_SERVER = "https://example.com";
const FAKE_OPENWHISK_AUTH = "c3VwZXItc2VjcmV0LWtleQ==";
const FAKE_OPENWHISK_NAMESPACE = "test";

const WSKDEBUG_BACKUP_ACTION_SUFFIX = "_wskdebug_original";

let openwhisk;

function isDockerInstalled() {
    try {
        execSync("docker info", {stdio: 'ignore'});
    } catch (e) {
        throw new Error("Docker not available or running on local system. These unit tests require it.")
    }
}

async function beforeEach() {
    process.env.WSK_CONFIG_FILE = path.join(process.cwd(), "test/wskprops");
    // nock.recorder.rec({ enable_reqheaders_recording: true });
    openwhisk = nock(FAKE_OPENWHISK_SERVER);
    // openwhisk.log(console.log);
    mockOpenwhiskSwagger(openwhisk);

    // save current working dir
    this.cwd = process.cwd();

    // find free port
    this.port = await getPort(9229);
    console.log("[test] free port:", this.port);
}

function afterEach() {
    delete process.env.WSK_CONFIG_FILE;
    nock.cleanAll();

    // restore working dir from beforeEach()
    process.chdir(this.cwd);
}

function assertAllNocksInvoked() {
    assert(
        openwhisk.isDone(),
        "Expected these HTTP requests: " + openwhisk.pendingMocks().join()
    );
}

function openwhiskNock() {
    return openwhisk;
}

function openwhiskApiUrlActions() {
    return `/api/v1/namespaces/${FAKE_OPENWHISK_NAMESPACE}/actions`;
}

function openwhiskApiAuthHeader() {
    return `Basic ${FAKE_OPENWHISK_AUTH}`;
}

function agentRetryResponse() {
    return {
        response: {
            success: false,
            result: {
                error: {
                    error: "Please retry.",
                    code: 42 // retry
                }
            }
        }
    };
}

function agentExitResponse() {
    return {
        response: {
            success: false,
            result: {
                error: {
                    error: "Please exit, thanks.",
                    code: 43 // graceful exit
                }
            }
        }
    };
}

function mockAction(name, code, binary=false) {
    // reading action without code
    openwhisk
        .get(`${openwhiskApiUrlActions()}/${name}`)
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .query({"code":"false"})
        .reply(200, nodejsActionDescription(name, binary));

    // with code
    const action = nodejsActionDescription(name, binary);
    action.exec.code = code;

    // reading action with code
    openwhisk
        .get(`${openwhiskApiUrlActions()}/${name}`)
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, action);
}

function mockCreateBackupAction(name, binary=false) {
    const backupName = name + WSKDEBUG_BACKUP_ACTION_SUFFIX;

    // wskdebug creating the backup action
    openwhisk
        .put(`${openwhiskApiUrlActions()}/${backupName}?overwrite=true`)
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, nodejsActionDescription(backupName, binary));
}

function mockInstallAgent(name) {
    // wskdebug overwriting the action with the agent
    openwhisk
        .put(
            `${openwhiskApiUrlActions()}/${name}?overwrite=true`,
            body => body.annotations.some(v => v.key === "wskdebug" && v.value === true)
        )
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, nodejsActionDescription(name));
}

function mockReadBackupAction(name, code, binary=false) {
    const backupName = name + WSKDEBUG_BACKUP_ACTION_SUFFIX;

    // reading it later on restore
    openwhisk
        .get(`${openwhiskApiUrlActions()}/${backupName}`)
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, Object.assign(nodejsActionDescription(backupName, binary), { exec: { code } }));
}

function mockRestoreAction(name, code, binary=false) {
    // restoring action
    openwhisk
        .put(
            `${openwhiskApiUrlActions()}/${name}?overwrite=true`,
            body => body.exec && body.exec.code === code
        )
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, nodejsActionDescription(name, binary));
}

function mockRemoveBackupAction(name) {
    const backupName = name + WSKDEBUG_BACKUP_ACTION_SUFFIX;

    // removing backup after restore
    openwhisk
        .delete(`${openwhiskApiUrlActions()}/${backupName}`)
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200);
}

function expectAgent(name, code, binary=false) {
    mockCreateBackupAction(name, binary);
    mockInstallAgent(name);

    // shutdown/restore process
    mockReadBackupAction(name, code, binary);
    mockRestoreAction(name, code, binary);
    mockRemoveBackupAction(name);
}

function nockActivation(name, bodyFn) {
    return openwhisk
        .post(`${openwhiskApiUrlActions()}/${name}`, bodyFn)
        .query(true) // support both ?blocking=true and non blocking (no query params)
        .matchHeader("authorization", openwhiskApiAuthHeader());
}

function mockAgentPoll(name) {
    return nockActivation(name, body => body.$waitForActivation === true)
        .optionally()
        .reply(502, agentRetryResponse())
        .persist();
}

function expectAgentInvocation(name, params, result) {
    params = params || {};
    const activationId = Date.now();
    result.$activationId = activationId;

    // wskdebug agent ping for new activation
    nockActivation(name, body => body.$waitForActivation === true)
        .reply(200, {
            response: {
                result: Object.assign(params, { $activationId: activationId })
            }
        });

    // wskdebug sending result back to agent
    nockActivation(
        name,
        body => {
            assert.deepStrictEqual(body, result);
            return true;
        }
    ).reply(200, {
        response: {
            result: {
                message: "Completed"
            }
        }
    });

    // graceful shutdown for wskdebug to end test
    nockActivation(name, body => body.$waitForActivation === true)
        .reply(502, {
            response: {
                success: false,
                result: {
                    error: {
                        error: "Please exit, thanks.",
                        code: 43 // graceful exit
                    }
                }
            }
        });
}

function mockActionAndInvocation(action, code, params, expectedResult, binary=false) {
    mockAction(action, code, binary);
    expectAgent(action, code, binary);

    expectAgentInvocation(action, params, expectedResult);
}

function mockActionDoubleInvocation(action, code, params, result1, runBetween, result2, binary=false) {
    params = params || {};
    const activationId = Date.now();
    result1.$activationId = activationId;

    mockAction(action, code, binary);
    expectAgent(action, code, binary);

    // 1st activation
    nockActivation(action, body => body.$waitForActivation === true)
        .reply(200, {
            response: {
                result: Object.assign(params, { $activationId: activationId })
            }
        });

    // wskdebug sending result back to agent
    nockActivation(
        action,
        body => {
            assert.deepStrictEqual(body, result1);
            return true;
        }
    ).reply(200, {
        response: {
            result: {
                message: "Completed"
            }
        }
    });

    // 2nd activation
    const activationId2 = Date.now() + "-second";
    result2.$activationId = activationId2;

    nockActivation(action, body => body.$waitForActivation === true)
        .reply(200, () => {
            runBetween();
            return {
                response: {
                    result: Object.assign(params, { $activationId: activationId2 })
                }
            }
        });

    // wskdebug sending 2nd result back to agent
    nockActivation(
        action,
        body => {
            assert.deepStrictEqual(body, result2);
            return true;
        }
    ).reply(200, {
        response: {
            result: {
                message: "Completed"
            }
        }
    });

    // graceful shutdown for wskdebug to end test
    nockActivation(action, body => body.$waitForActivation === true)
        .reply(502, {
            response: {
                success: false,
                result: {
                    error: {
                        error: "Please exit, thanks.",
                        code: 43 // graceful exit
                    }
                }
            }
        });
}

// --------------------------------------------< internal >---------------

function nodejsActionDescription(name, binary=false) {
    return {
        "annotations":[
            { "key": "exec", "value": "nodejs:10" },
            { "key": "provide-api-key", "value": true }
        ],
        "exec":{
            "kind": "nodejs:10",
            "binary": binary
        },
        "limits":{
            "concurrency": 200,
            "logs": 10,
            "memory": 256,
            "timeout": 300000
        },
        "name": name,
        "namespace": FAKE_OPENWHISK_NAMESPACE,
        "parameters": [],
        "publish": false,
        "version": "0.0.1"
    };
}

function mockOpenwhiskSwagger(openwhisk) {
    // mock swagger api response
    openwhisk
        .get('/')
        .optionally()
        .matchHeader("accept", "application/json")
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, {
            "api_paths": ["/api/v1"],
            "description": "OpenWhisk",
            "limits": {
                "actions_per_minute":600,
                "concurrent_actions":100,
                "max_action_duration":3600000,
                "max_action_logs":10485760,
                "max_action_memory":52428800000,
                "min_action_duration":100,
                "min_action_logs":0,
                "min_action_memory":134217728,
                "sequence_length":50,
                "triggers_per_minute":600
            },
            "runtimes":{
                "nodejs": [
                    {
                        "kind":"nodejs:10",
                        "attached":true,
                        "default":true,
                        "deprecated":false,
                        "image":"bladerunner/adobe-action-nodejs-v10:3.0.21",
                        "requireMain":false
                    },{
                        "kind":"nodejs",
                        "attached":true,
                        "default":false,
                        "deprecated":true,
                        "image":"bladerunner/adobe-action-nodejs-v10-fat:3.0.17",
                        "requireMain":false
                    },{
                        "kind":"nodejs:10-fat",
                        "attached":true,
                        "default":false,
                        "deprecated":true,
                        "image":"bladerunner/adobe-action-nodejs-v10-fat:3.0.17",
                        "requireMain":false
                    },{
                        "kind":"nodejs:6",
                        "attached":true,
                        "default":false,
                        "deprecated":true,
                        "image":"bladerunner/adobe-action-nodejs-v10-fat:3.0.17",
                        "requireMain":false
                    },{
                        "kind":"nodejs:8",
                        "attached":true,
                        "default":false,
                        "deprecated":true,
                        "image":"bladerunner/adobe-action-nodejs-v10-fat:3.0.17",
                        "requireMain":false
                    }
                ]
            },
            "support":{
                "github":"https://github.com/apache/openwhisk/issues",
                "slack":"http://slack.openwhisk.org"
            }
        });

    openwhisk
        .get('/api/v1')
        .optionally()
        .matchHeader("accept", "application/json")
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200,{
            "api_version":"1.0.0",
            "api_version_path":"v1",
            "build":"2019-11-08 - a",
            "buildno":"v58 - runtime-prs-v59-f7774d5",
            "description":"OpenWhisk API",
            "swagger_paths": {
                "api-docs":"/api-docs",
                "ui":"/docs"
            }
        });

    openwhisk
        .get('/api/v1/api-docs')
        .optionally()
        .matchHeader("accept", "application/json")
        .matchHeader("authorization", openwhiskApiAuthHeader())
        .reply(200, JSON.parse(fs.readFileSync("./test/openwhisk-swagger.json")));
}

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

let capture;

function startCaptureStdout() {
    endCaptureStdout();
    global.disableMochaLogFile = true;

    capture = {
        stdout: "",
        stderr: "",
        original: {
            stdoutWrite: process.stdout.write,
            stderrWrite: process.stderr.write
        }
    };
    process.stdout.write = function(string) {
        capture.stdout += string;
    };
    process.stderr.write = function(string) {
        capture.stderr += string;
    };
}

function endCaptureStdout() {
    delete global.disableMochaLogFile;

    if (capture && capture.original) {
        process.stdout.write = capture.original.stdoutWrite;
        process.stderr.write = capture.original.stderrWrite;
        delete capture.original;
    }
    if (capture) {
        return {
            stdout: capture.stdout,
            stderr: capture.stderr
        };
    } else {
        return {};
    }
}

async function sleep(millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}

function touchFile(file) {
    fs.utimesSync(file, Date.now(), Date.now());
}

function hasNotTimedOut(testCtx) {
    if (!testCtx.test) {
        return false;
    }
    if (testCtx.test.__deadline === undefined) {
        testCtx.test.__deadline = Date.now() + testCtx.timeout() * 0.8;
        return true;
    }
    return Date.now() < testCtx.test.__deadline;
}

// --------------------------------------------< exports >---------------

module.exports = {
    isDockerInstalled,
    beforeEach,
    afterEach,
    assertAllNocksInvoked,
    // mock
    mockActionAndInvocation,
    mockActionDoubleInvocation,
    // advanced
    openwhiskNock,
    openwhiskApiUrlActions,
    openwhiskApiAuthHeader,
    mockAction,
    mockCreateBackupAction,
    mockInstallAgent,
    mockReadBackupAction,
    mockRestoreAction,
    mockRemoveBackupAction,
    nodejsActionDescription,
    expectAgent,
    nockActivation,
    expectAgentInvocation,
    mockAgentPoll,
    agentRetryResponse,
    agentExitResponse,
    // utils
    startCaptureStdout,
    endCaptureStdout,
    sleep,
    touchFile,
    hasNotTimedOut
}
