"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.WorkerPool = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
/**
 * @author Deepkolos / https://github.com/deepkolos
 */
var WorkerPool = /*#__PURE__*/function () {
  function WorkerPool() {
    var pool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4;
    (0, _classCallCheck2["default"])(this, WorkerPool);
    this.pool = pool;
    this.queue = [];
    this.workers = [];
    this.workersResolve = [];
    this.workerStatus = 0;
  }
  (0, _createClass2["default"])(WorkerPool, [{
    key: "_initWorker",
    value: function _initWorker(workerId) {
      if (!this.workers[workerId]) {
        var worker = this.workerCreator();
        worker.addEventListener('message', this._onMessage.bind(this, workerId));
        this.workers[workerId] = worker;
      }
    }
  }, {
    key: "_getIdleWorker",
    value: function _getIdleWorker() {
      for (var i = 0; i < this.pool; i++) if (!(this.workerStatus & 1 << i)) return i;
      return -1;
    }
  }, {
    key: "_onMessage",
    value: function _onMessage(workerId, msg) {
      var resolve = this.workersResolve[workerId];
      resolve && resolve(msg);
      if (this.queue.length) {
        var _this$queue$shift = this.queue.shift(),
          _resolve = _this$queue$shift.resolve,
          _msg = _this$queue$shift.msg,
          transfer = _this$queue$shift.transfer;
        this.workersResolve[workerId] = _resolve;
        this.workers[workerId].postMessage(_msg, transfer);
      } else {
        this.workerStatus ^= 1 << workerId;
      }
    }
  }, {
    key: "setWorkerCreator",
    value: function setWorkerCreator(workerCreator) {
      this.workerCreator = workerCreator;
    }
  }, {
    key: "setWorkerLimit",
    value: function setWorkerLimit(pool) {
      this.pool = pool;
    }
  }, {
    key: "postMessage",
    value: function postMessage(msg, transfer) {
      var _this = this;
      return new Promise(function (resolve) {
        var workerId = _this._getIdleWorker();
        if (workerId !== -1) {
          _this._initWorker(workerId);
          _this.workerStatus |= 1 << workerId;
          _this.workersResolve[workerId] = resolve;
          _this.workers[workerId].postMessage(msg, transfer);
        } else {
          _this.queue.push({
            resolve: resolve,
            msg: msg,
            transfer: transfer
          });
        }
      });
    }
  }, {
    key: "dispose",
    value: function dispose() {
      this.workers.forEach(function (worker) {
        return worker.terminate();
      });
      this.workersResolve.length = 0;
      this.workers.length = 0;
      this.queue.length = 0;
      this.workerStatus = 0;
    }
  }]);
  return WorkerPool;
}();
exports.WorkerPool = WorkerPool;