"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.INTERACTIVE_KEYS = void 0;

function _bluebird() {
  const data = require("bluebird");

  _bluebird = function () {
    return data;
  };

  return data;
}

function _execa() {
  const data = _interopRequireDefault(require("execa"));

  _execa = function () {
    return data;
  };

  return data;
}

function _padRight() {
  const data = _interopRequireDefault(require("pad-right"));

  _padRight = function () {
    return data;
  };

  return data;
}

function _chalk() {
  const data = _interopRequireDefault(require("chalk"));

  _chalk = function () {
    return data;
  };

  return data;
}

function _pSeries() {
  const data = _interopRequireDefault(require("p-series"));

  _pSeries = function () {
    return data;
  };

  return data;
}

const DEFAULT_DEFAULT_INTERVAL_BETWEEN_INPUTS = 100;
const INTERACTIVE_KEYS = {
  up: {
    label: 'up',
    value: '\x1B\x5B\x41'
  },
  down: {
    label: 'down',
    value: '\x1B\x5B\x42'
  },
  enter: {
    label: 'enter',
    value: '\x0D'
  },
  space: {
    label: 'space',
    value: '\x20'
  }
}; // Based on (with a lot of modifications):
// https://github.com/ewnd9/inquirer-test/blob/6e2c40bbd39a061d3e52a8b1ee52cdac88f8d7f7/index.js#L14
// https://medium.com/@zorrodg/integration-tests-on-node-js-cli-part-2-testing-interaction-user-input-6f345d4b713a

exports.INTERACTIVE_KEYS = INTERACTIVE_KEYS;

var _default =
/*#__PURE__*/
function () {
  var _runInteractive = (0, _bluebird().coroutine)(function* ({
    processName,
    args = [],
    inputs = [],
    // Options for the process (execa)
    processOpts = {
      cwd: '/tmp/aa'
    },
    // opts for interactive
    opts = {
      defaultIntervalBetweenInputs: DEFAULT_DEFAULT_INTERVAL_BETWEEN_INPUTS,
      verbose: false
    }
  }) {
    const actualDefaultIntervalBetweenInputs = opts.defaultIntervalBetweenInputs || DEFAULT_DEFAULT_INTERVAL_BETWEEN_INPUTS;

    if (opts.verbose) {
      console.log((0, _padRight().default)(_chalk().default.green('cwd: '), 20, ' '), processOpts.cwd); // eslint-disable-line no-console

      console.log((0, _padRight().default)(_chalk().default.green('command: '), 20, ' '), `${processName} ${args.join(' ')}`); // eslint-disable-line no-console

      _printInputs(inputs, actualDefaultIntervalBetweenInputs);
    }

    const child = (0, _execa().default)(processName, args, processOpts);
    child.stdin.setEncoding('utf-8');
    let currentInputTimeout;

    const writePromiseTimeout =
    /*#__PURE__*/
    function () {
      var _ref = (0, _bluebird().coroutine)(function* (input) {
        return new Promise(resolve => {
          const timeout = input.waitInput || actualDefaultIntervalBetweenInputs;
          const inputValue = typeof input.value === 'string' ? input.value : input.value.value;
          currentInputTimeout = setTimeout(() => {
            child.stdin.write(inputValue);
            resolve();
          }, timeout);
        });
      });

      return function writePromiseTimeout(_x2) {
        return _ref.apply(this, arguments);
      };
    }();
    /**
     * A function to wrap the promise with another function to prepare it for p-series
     * @param {*} input
     */


    const wrapInputWriting = input => () => writePromiseTimeout(input);

    const writeInputsArray =
    /*#__PURE__*/
    function () {
      var _ref2 = (0, _bluebird().coroutine)(function* (inputsArr) {
        const writeInputsP = inputsArr.map(wrapInputWriting);
        return (0, _pSeries().default)(writeInputsP);
      });

      return function writeInputsArray(_x3) {
        return _ref2.apply(this, arguments);
      };
    }();

    child.stderr.once('data', () => {
      console.log('got an error from child'); // eslint-disable-line no-console
      // If child errors out, stop all the pending inputs if any

      child.stdin.end();

      if (currentInputTimeout) {
        clearTimeout(currentInputTimeout);
        inputs = [];
      }
    }); // Kick off the process

    let pointer = 0;
    let leftInputsArrays = inputs.length;
    child.stdout.on('data', chunk => {
      const currString = chunk.toString();

      if (pointer < inputs.length) {
        const triggerText = inputs[pointer].triggerText; // We remove the eol since sometime interactive frameworks added line breaks if the question is too long

        if (_removeEol(currString).includes(_removeEol(triggerText))) {
          const inputsToWrite = inputs[pointer].inputs;
          writeInputsArray(inputsToWrite).then(() => {
            leftInputsArrays -= 1; // Finished to write all - end stream

            if (leftInputsArrays === 0) {
              child.stdin.end();
            }
          });
          pointer += 1;
        }
      }
    });
    return child;
  });

  function runInteractive(_x) {
    return _runInteractive.apply(this, arguments);
  }

  return runInteractive;
}();

exports.default = _default;

function _printInputs(inputsToPrint, actualDefaultIntervalBetweenInputs) {
  const getTriggerOutput = trigger => {
    return `${_chalk().default.blue('trigger:')} ${trigger} `;
  };

  const getInputOutput = input => {
    const timeout = input.waitInput || actualDefaultIntervalBetweenInputs;
    const label = typeof input.value === 'string' ? input.value : input.value.label;
    return `${label}(${timeout})`;
  };

  const getInputsOutput = inputs => {
    const inputsOutput = inputs.map(getInputOutput).join(' ');
    return `${_chalk().default.yellow('inputs:')} ${inputsOutput}`;
  };

  const getEntryOutput = entry => {
    const triggerOutput = getTriggerOutput(entry.triggerText);
    const inputsOutput = getInputsOutput(entry.inputs);
    return `${triggerOutput} ${inputsOutput}`;
  };

  const output = inputsToPrint.map(getEntryOutput).join('\n');
  console.log((0, _padRight().default)(_chalk().default.green('inputs:\n'), 20, ''), output); // eslint-disable-line no-console
}

function _removeEol(str) {
  return str.replace(/\n/, '');
}