"use strict";

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

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.appendFeature = appendFeature;
exports.destroyFeature = destroyFeature;
exports.toggleFeature = toggleFeature;
exports.reset = reset;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

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

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

var _Fetcher = _interopRequireDefault(require("../../common/util/Fetcher"));

var _loader = _interopRequireDefault(require("./loader"));

var questionsApp;
var authPromise;

function appendFeature(_x, _x2, _x3) {
  return _appendFeature.apply(this, arguments);
}

function _appendFeature() {
  _appendFeature = (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee(quizSessionId, feature, timeout) {
    var _len,
        args,
        _key,
        _args = arguments;

    return _regenerator.default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            if (questionsApp) {
              _context.next = 5;
              break;
            }

            for (_len = _args.length, args = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
              args[_key - 3] = _args[_key];
            }

            _context.next = 4;
            return authenticate.apply(void 0, [quizSessionId].concat(args));

          case 4:
            questionsApp = _context.sent;

          case 5:
            if (!featureContainer(feature.feature_id)) {
              _context.next = 11;
              break;
            }

            questionsApp.append({
              features: [feature]
            });
            _context.next = 9;
            return waitForLearnosityReadyCallback(timeout, feature.feature_id);

          case 9:
            _context.next = 12;
            break;

          case 11:
            throw new Error('Learnosity feature container element not found');

          case 12:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _appendFeature.apply(this, arguments);
}

function destroyFeature(featureId) {
  if (!questionsApp) return;
  var feature = questionsApp.feature(featureId);

  if (feature) {
    feature.destroy();
  }
}

function toggleFeature(featureId, onOff) {
  if (!questionsApp) return;
  var feature = questionsApp.feature(featureId);

  if (feature) {
    feature.toggle(onOff);
  }
}

function featureContainer(featureId) {
  return document.querySelector(".learnosity-feature.feature-".concat(featureId));
}

function authenticate(quizSessionId) {
  var loader = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : _loader.default;
  var fetcher = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : null;
  authPromise = authPromise || new Promise(function (resolve, reject) {
    var f = fetcher || new _Fetcher.default();
    Promise.all([loader(), f.post("/api/quiz_sessions/".concat(quizSessionId, "/learnosity_authentication?domain=").concat(window.location.hostname))]).then(function (_ref) {
      var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
          app = _ref2[0],
          response = _ref2[1];

      var questionsApp = app.init(response, {
        errorListener: function errorListener(e) {
          authPromise = null;
          reject(e);
        },
        readyListener: function readyListener() {
          authPromise = null;
          resolve(questionsApp);
          learnosityReady();
        }
      });
    }).catch(function (e) {
      authPromise = null;
      reject(e);
    });
  });
  return authPromise;
} // Learnosity calls readyListener when it has finished loading, and again when
// a feature has been appended to the DOM. The following is gross, but it
// allows us to await until a feature is ready.


var pendingFeaturesPromise, pendingFeatures, pendingCount;

function resetPending() {
  pendingFeaturesPromise = null;
  pendingFeatures = {};
  pendingCount = 0;
}

resetPending();

function learnosityReady() {
  // We can't know which  feature is ready, so only resolve once there are
  // no more pending features
  if (pendingCount > 0) {
    pendingCount -= 1;

    if (pendingCount === 0) {
      pendingFeaturesPromise.resolve();
      resetPending();
    }
  }
}

function waitForLearnosityReadyCallback() {
  var timeout = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 5000;
  var featureId = arguments.length > 1 ? arguments[1] : void 0;

  if (!pendingFeatures[featureId]) {
    pendingCount += 1;
    pendingFeatures[featureId] = true;
    var res;

    if (!pendingFeaturesPromise) {
      pendingFeaturesPromise = new Promise(function (resolve, reject) {
        var timer = setTimeout(function () {
          reject(new Error('Timed out waiting for learnosity ready callback'));
          resetPending();
        }, timeout);

        res = function res() {
          clearTimeout(timer);
          resolve();
        };
      });
      pendingFeaturesPromise.resolve = res;
    }
  }

  return pendingFeaturesPromise;
} // Only used to reset singleton state for tests


function reset() {
  questionsApp = null;
  authPromise = null;
  resetPending();
}