'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.cleanupKernel = cleanupKernel;
exports.forceShutdownKernel = forceShutdownKernel;
exports.shutdownKernel = shutdownKernel;

var _fs2 = require('fs');

var fs = _interopRequireWildcard(_fs2);

var _enchannel = require('enchannel');

var _messaging = require('./messaging');

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function cleanupKernel(kernel, closeChannels, _fs = fs) {
  if (kernel.channels && closeChannels) {
    try {
      kernel.channels.shell.complete();
      kernel.channels.iopub.complete();
      kernel.channels.stdin.complete();
      kernel.channels.control.complete();
    } catch (err) {
      // nom nom nom
      console.warn(`Could not cleanup kernel channels, have they already
        been completed?`, kernel.channels);
    }
  }

  if (kernel.spawn) {
    try {
      kernel.spawn.stdin.destroy();
      kernel.spawn.stdout.destroy();
      kernel.spawn.stderr.destroy();
    } catch (err) {
      // nom nom nom
      console.warn(`Could not cleanup kernel process stdio, have they already
        been destroyed?`, kernel.spawn);
    }
  }
  if (kernel.connectionFile) {
    _fs.unlinkSync(kernel.connectionFile);
  }
}

function forceShutdownKernel(kernel, _fs = fs) {
  if (kernel && kernel.spawn && kernel.spawn.kill) {
    kernel.spawn.kill('SIGKILL');
  }

  cleanupKernel(kernel, true, _fs);
}

function shutdownKernel(kernel) {
  // Validate the input, do nothing if invalid kernel info is provided.
  if (!(kernel && (kernel.channels || kernel.spawn))) {
    return Promise.resolve();
  }

  // Fallback to forcefully shutting the kernel down.
  function handleShutdownFailure(err) {
    console.error(`Could not gracefully shutdown the kernel because of the
      following error.  nteract will now forcefully shutdown the kernel.`, err);
    forceShutdownKernel(kernel);
  }

  // Attempt to gracefully terminate the kernel.
  try {
    return (0, _enchannel.shutdownRequest)(kernel.channels, (0, _messaging.getUsername)(), _messaging.session, false).then(() => {
      // At this point, the kernel has cleaned up its resources.  Now we can
      // terminate the process and cleanup handles by calling forceShutdownKernel
      forceShutdownKernel(kernel);
    }).catch(handleShutdownFailure);
  } catch (err) {
    handleShutdownFailure(err);
    return Promise.reject(err);
  }
}