"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = server;
var _path = _interopRequireDefault(require("path"));
var _http = _interopRequireDefault(require("http"));
var _cluster = _interopRequireDefault(require("cluster"));
var _koa = _interopRequireDefault(require("koa"));
var _cors = _interopRequireDefault(require("@koa/cors"));
var _koaStatic = _interopRequireDefault(require("koa-static"));
var _koaMount = _interopRequireDefault(require("koa-mount"));
var _koaBodyparser = _interopRequireDefault(require("koa-bodyparser"));
var _ws = _interopRequireDefault(require("ws"));
var _messages = require("../messages");
var _types = require("../../types");
var _logger = require("../logger");
var _shared = require("../../shared");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function server(reportDir, port, ui) {
  let resolveApi = _types.noop;
  let setStoriesCounter = 0;
  const creeveyApi = new Promise(resolve => resolveApi = resolve);
  const app = new _koa.default();
  const server = _http.default.createServer(app.callback());
  const wss = new _ws.default.Server({
    server
  });
  app.use((0, _cors.default)());
  app.use((0, _koaBodyparser.default)());
  app.use(async (ctx, next) => {
    if (ctx.method == 'GET' && ctx.path == '/ping') {
      ctx.body = 'pong';
      return;
    }
    await next();
  });
  if (ui) {
    app.use(async (_, next) => {
      await creeveyApi;
      await next();
    });
  }
  app.use(async (ctx, next) => {
    if (ctx.method == 'POST' && ctx.path == '/stories') {
      const {
        setStoriesCounter: counter,
        stories
      } = ctx.request.body;
      if (setStoriesCounter >= counter) return;
      const deserializedStories = stories.map(([file, stories]) => [file, stories.map(_shared.deserializeStory)]);
      setStoriesCounter = counter;
      (0, _messages.emitStoriesMessage)({
        type: 'update',
        payload: deserializedStories
      });
      Object.values(_cluster.default.workers ?? {}).filter(_types.isDefined).filter(worker => worker.isConnected()).forEach(worker => (0, _messages.sendStoriesMessage)(worker, {
        type: 'update',
        payload: deserializedStories
      }));
      return;
    }
    await next();
  });
  app.use(async (ctx, next) => {
    if (ctx.method == 'POST' && ctx.path == '/capture') {
      const {
        workerId,
        options
      } = ctx.request.body;
      const worker = Object.values(_cluster.default.workers ?? {}).filter(_types.isDefined).find(worker => worker.process.pid == workerId);
      // NOTE: Hypothetical case when someone send to us capture req and we don't have a worker with browser session for it
      if (!worker) return;
      await new Promise(resolve => {
        const unsubscribe = (0, _messages.subscribeOnWorker)(worker, 'stories', message => {
          if (message.type != 'capture') return;
          unsubscribe();
          resolve();
        });
        (0, _messages.sendStoriesMessage)(worker, {
          type: 'capture',
          payload: options
        });
      });
      // TODO Pass screenshot result to show it in inspector
      ctx.body = 'Ok';
      return;
    }
    await next();
  });
  app.use((0, _koaStatic.default)(_path.default.join(__dirname, '../../client/web')));
  app.use((0, _koaMount.default)('/report', (0, _koaStatic.default)(reportDir)));
  wss.on('error', error => _logger.logger.error(error));
  server.listen(port);
  (0, _messages.subscribeOn)('shutdown', () => {
    server.close();
    wss.close();
    wss.clients.forEach(ws => ws.close());
  });
  void creeveyApi.then(api => {
    api.subscribe(wss);
    wss.on('connection', ws => {
      ws.on('message', (message, isBinary) => {
        api.handleMessage(ws, isBinary ? message : message.toString());
      });
    });
  });
  return resolveApi;
}