'use strict';

const assert = require('assert');
const common = require('./common');

// we only check async hooks on 8.x an higher were
// they are closer to working properly
const nodeVersion = process.versions.node.split('.')[0];
let asyncHooks;
function checkAsyncHooks () {
  if (nodeVersion >= 8) {
    if (asyncHooks === undefined) {
      asyncHooks = require('async_hooks');
    }
    return true;
  }
  return false;
}

module.exports = common.runTest(test);

function installAsyncHooksForTest (resName) {
  return new Promise((resolve, reject) => {
    let id;
    const events = [];
    /**
     * TODO(legendecas): investigate why resolving & disabling hooks in
     * destroy callback causing crash with case 'callbackscope.js'.
     */
    let destroyed = false;
    const hook = asyncHooks.createHook({
      init (asyncId, type, triggerAsyncId, resource) {
        if (id === undefined && type === resName) {
          id = asyncId;
          events.push({ eventName: 'init', type, triggerAsyncId, resource });
        }
      },
      before (asyncId) {
        if (asyncId === id) {
          events.push({ eventName: 'before' });
        }
      },
      after (asyncId) {
        if (asyncId === id) {
          events.push({ eventName: 'after' });
        }
      },
      destroy (asyncId) {
        if (asyncId === id) {
          events.push({ eventName: 'destroy' });
          destroyed = true;
        }
      }
    }).enable();

    const interval = setInterval(() => {
      if (destroyed) {
        hook.disable();
        clearInterval(interval);
        resolve(events);
      }
    }, 10);
  });
}

async function makeCallbackWithResource (binding) {
  const hooks = installAsyncHooksForTest('async_context_test');
  const triggerAsyncId = asyncHooks.executionAsyncId();
  await new Promise((resolve, reject) => {
    binding.asynccontext.makeCallback(common.mustCall(), { foo: 'foo' });
    hooks.then(actual => {
      assert.deepStrictEqual(actual, [
        {
          eventName: 'init',
          type: 'async_context_test',
          triggerAsyncId,
          resource: { foo: 'foo' }
        },
        { eventName: 'before' },
        { eventName: 'after' },
        { eventName: 'destroy' }
      ]);
    }).catch(common.mustNotCall());
    resolve();
  });
}

async function makeCallbackWithoutResource (binding) {
  const hooks = installAsyncHooksForTest('async_context_no_res_test');
  const triggerAsyncId = asyncHooks.executionAsyncId();
  await new Promise((resolve, reject) => {
    binding.asynccontext.makeCallbackNoResource(common.mustCall());
    hooks.then(actual => {
      assert.deepStrictEqual(actual, [
        {
          eventName: 'init',
          type: 'async_context_no_res_test',
          triggerAsyncId,
          resource: { }
        },
        { eventName: 'before' },
        { eventName: 'after' },
        { eventName: 'destroy' }
      ]);
    }).catch(common.mustNotCall());
    resolve();
  });
}

function assertAsyncContextReturnsCorrectEnv (binding) {
  assert.strictEqual(binding.asynccontext.asyncCxtReturnCorrectEnv(), true);
}

async function test (binding) {
  if (!checkAsyncHooks()) {
    return;
  }

  await makeCallbackWithResource(binding);
  await makeCallbackWithoutResource(binding);
  assertAsyncContextReturnsCorrectEnv(binding);
}
