'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.copyAsync = copyAsync;
exports.runCmd = runCmd;
exports.assertOnlyFiles = assertOnlyFiles;
exports.readJSON = readJSON;
exports.runGen = runGen;

var _path = require('path');

var _path2 = _interopRequireDefault(_path);

var _fs = require('fs');

var _fs2 = _interopRequireDefault(_fs);

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _bluebird = require('bluebird');

var _bluebird2 = _interopRequireDefault(_bluebird);

var _child_process = require('child_process');

var _yeomanTest = require('yeoman-test');

var _yeomanTest2 = _interopRequireDefault(_yeomanTest);

var _yeomanAssert = require('yeoman-assert');

var _yeomanAssert2 = _interopRequireDefault(_yeomanAssert);

var _recursiveReaddir = require('recursive-readdir');

var _recursiveReaddir2 = _interopRequireDefault(_recursiveReaddir);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var TEST_DIR = __dirname;

/**
 * Copy file from src to dest
 * @param {string} src
 * @param {string} dest
 * @returns {Promise}
 */
function copyAsync(src, dest) {
  return _fs2.default.readFileAsync(src).then(function (data) {
    return _fs2.default.writeFileAsync(dest, data);
  });
}

/**
 * @callback doneCallback
 * @param {null|Error} err
 */

/**
 * Run the given command in a child process
 * @param {string} cmd - command to run
 * @returns {Promise}
 */
function runCmd(cmd) {
  return new _bluebird2.default(function (resolve, reject) {
    (0, _child_process.exec)(cmd, { maxBuffer: 1024 * 500 }, function (err, stdout, stderr) {
      if (err) {
        console.error(stdout);
        return reject(err);
      } else {
        if (DEBUG) console.log(cmd + ' stdout: ' + stdout);
        return resolve();
      }
    });
  });
}

/**
 * Assert that only the expected files are present
 * @param {string[]} expectedFiles - array of expected files
 * @param {string} [topLevelPath='./'] - root dir of expected files to recursively search
 * @param {string[]} [skip=['node_modules','bower_components']] - files/folders recursiveReadDir should skip
 * @returns {Promise}
 */
function assertOnlyFiles(expectedFiles) {
  var topLevelPath = arguments.length <= 1 || arguments[1] === undefined ? './' : arguments[1];
  var skip = arguments.length <= 2 || arguments[2] === undefined ? ['node_modules', 'bower_components'] : arguments[2];

  return new _bluebird2.default(function (resolve, reject) {
    (0, _recursiveReaddir2.default)(topLevelPath, skip, function (err, actualFiles) {
      if (err) return reject(err);

      actualFiles = _lodash2.default.map(actualFiles.concat(), function (file) {
        return _path2.default.normalize(file.replace(_path2.default.normalize(topLevelPath + '/'), ''));
      });
      expectedFiles = _lodash2.default.map(expectedFiles, function (file) {
        return _path2.default.normalize(file);
      });

      var extras = _lodash2.default.pullAll(actualFiles, expectedFiles);

      if (extras.length !== 0) {
        return reject(extras);
      }
      resolve();
    });
  });
}

/**
 * Read JSON from a file
 * @param {string} path
 * @returns {Promise} - parsed JSON
 */
function readJSON(path) {
  return _fs2.default.readFileAsync(path, 'utf8').then(function (data) {
    return JSON.parse(data);
  });
}

/**
 * Run angular-fullstack:app
 * @param {object} [prompts]
 * @param {object} [opts={}]
 * @param {boolean} [opts.copyConfigFile] - copy default .yo-rc.json
 * @returns {Promise}
 */
function runGen(prompts) {
  var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

  var options = opts.options || { skipInstall: true };

  // let dir;
  var gen = _yeomanTest2.default.run(require.resolve('../generators/app')).inTmpDir(function (dir) {
    // this will create a new temporary directory for each new generator run
    var done = this.async();
    if (DEBUG) console.log('TEMP DIR: ' + dir);

    var promises = [_fs2.default.symlinkAsync(__dirname + '/fixtures/node_modules', dir + '/node_modules')];

    if (opts.copyConfigFile) {
      promises.push(copyAsync(_path2.default.join(TEST_DIR, 'fixtures/.yo-rc.json'), _path2.default.join(dir, '.yo-rc.json')));
    }

    // symlink our dependency directories
    return _bluebird2.default.all(promises).then(done);
  }).withGenerators([require.resolve('../generators/endpoint')])
  // .withArguments(['upperCaseBug'])
  .
  // [helpers.createDummyGenerator(), 'ng-component:app']
  withOptions(options);

  if (prompts) gen.withPrompts(prompts);

  return gen.toPromise();
}