"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = _default;
var _path = _interopRequireDefault(require("path"));
var _fs = require("fs");
var _util = require("util");
var _master = _interopRequireDefault(require("./master"));
var _api = _interopRequireDefault(require("./api"));
var _types = require("../../types");
var _utils = require("../utils");
var _messages = require("../messages");
var _logger = require("../logger");
var _telemetry = require("../telemetry");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const writeFileAsync = (0, _util.promisify)(_fs.writeFile);
const copyFileAsync = (0, _util.promisify)(_fs.copyFile);
const readdirAsync = (0, _util.promisify)(_fs.readdir);
const mkdirAsync = (0, _util.promisify)(_fs.mkdir);
async function copyStatics(reportDir) {
  const clientDir = _path.default.join(__dirname, '../../client/web');
  const files = (await readdirAsync(clientDir, {
    withFileTypes: true
  })).filter(dirent => dirent.isFile() && !dirent.name.endsWith('.d.ts') && !dirent.name.endsWith('.tsx')).map(dirent => dirent.name);
  await mkdirAsync(reportDir, {
    recursive: true
  });
  for (const file of files) {
    await copyFileAsync(_path.default.join(clientDir, file), _path.default.join(reportDir, file));
  }
}
function reportDataModule(data) {
  return `
(function (root, factory) {
  if (typeof module === 'object' && module.exports) {
    module.exports = factory();
  } else {
    root.__CREEVEY_DATA__ = factory();
  }
}(this, function () { return ${JSON.stringify(data)} }));
`;
}
function outputUnnecessaryImages(imagesDir, images) {
  if (!(0, _fs.existsSync)(imagesDir)) return;
  const unnecessaryImages = (0, _utils.readDirRecursive)(imagesDir).map(imagePath => _path.default.posix.relative(imagesDir, imagePath)).filter(imagePath => !images.has(imagePath));
  if (unnecessaryImages.length > 0) {
    _logger.logger.warn('We found unnecessary screenshot images, those can be safely removed:\n', unnecessaryImages.join('\n'));
  }
}
async function _default(config, options, resolveApi) {
  let runner = null;
  if (config.hooks.before) {
    await config.hooks.before();
  }
  (0, _messages.subscribeOn)('shutdown', () => {
    var _config$hooks$after, _config$hooks;
    return (_config$hooks$after = (_config$hooks = config.hooks).after) === null || _config$hooks$after === void 0 ? void 0 : _config$hooks$after.call(_config$hooks);
  });
  process.removeListener('SIGINT', _utils.shutdown);
  process.on('SIGINT', () => {
    var _runner, _runner2;
    (_runner = runner) === null || _runner === void 0 || _runner.removeAllListeners('stop');
    if ((_runner2 = runner) !== null && _runner2 !== void 0 && _runner2.isRunning) {
      var _runner4;
      // TODO Better handle stop
      void Promise.race([new Promise(resolve => setTimeout(resolve, 10000)), new Promise(resolve => {
        var _runner3;
        return (_runner3 = runner) === null || _runner3 === void 0 ? void 0 : _runner3.once('stop', resolve);
      })]).then(() => (0, _utils.shutdownWorkers)());
      (_runner4 = runner) === null || _runner4 === void 0 || _runner4.stop();
    } else {
      void (0, _utils.shutdownWorkers)();
    }
  });
  runner = await (0, _master.default)(config, {
    watch: options.ui,
    debug: options.debug,
    port: options.port
  });
  if (options.saveReport) {
    runner.on('stop', () => {
      void copyStatics(config.reportDir).then(() => {
        var _runner5;
        return writeFileAsync(_path.default.join(config.reportDir, 'data.js'), reportDataModule((_runner5 = runner) === null || _runner5 === void 0 ? void 0 : _runner5.status.tests));
      });
    });
  }
  if (options.ui) {
    resolveApi((0, _api.default)(runner));
    _logger.logger.info(`Started on http://localhost:${options.port}`);
  } else {
    if (Object.values(runner.status.tests).filter(test => test && !test.skip).length == 0) {
      _logger.logger.warn("Don't have any tests to run");
      // eslint-disable-next-line no-process-exit
      void (0, _utils.shutdownWorkers)().then(() => process.exit());
      return;
    }
    runner.once('stop', () => {
      var _runner6, _runner7;
      const tests = Object.values(((_runner6 = runner) === null || _runner6 === void 0 ? void 0 : _runner6.status.tests) ?? {});
      const isSuccess = tests.filter(_types.isDefined).filter(({
        skip
      }) => !skip).every(({
        status
      }) => status == 'success');
      // TODO output summary
      process.exitCode = isSuccess ? 0 : -1;
      if (!config.failFast) outputUnnecessaryImages(config.screenDir, (0, _utils.testsToImages)(tests));
      (0, _telemetry.sendScreenshotsCount)(config, options, (_runner7 = runner) === null || _runner7 === void 0 ? void 0 : _runner7.status).catch(reason => {
        const error = reason instanceof Error ? reason.stack ?? reason.message : reason;
        _logger.logger.warn(`Can't send telemetry: ${error}`);
      }).finally(() => {
        // eslint-disable-next-line no-process-exit
        void (0, _utils.shutdownWorkers)().then(() => process.exit());
      });
    });
    // TODO grep
    runner.start(Object.keys(runner.status.tests));
  }
}