"use strict";

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

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.Main = void 0;

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

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

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

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

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

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

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

var _react = _interopRequireDefault(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _correctAnswerToggle = require("@pie-lib/pie-toolbox/correct-answer-toggle");

var _mathInput = require("@pie-lib/pie-toolbox/math-input");

var _renderUi = require("@pie-lib/pie-toolbox/render-ui");

var _mathRendering = require("@pie-lib/pie-toolbox/math-rendering");

var _styles = require("@material-ui/core/styles");

var _Tooltip = _interopRequireDefault(require("@material-ui/core/Tooltip"));

var _utils = require("./utils");

var _isEqual = _interopRequireDefault(require("lodash/isEqual"));

var _classnames = _interopRequireDefault(require("classnames"));

var _simpleQuestionBlock = _interopRequireDefault(require("./simple-question-block"));

var _mathquill = _interopRequireDefault(require("@pie-framework/mathquill"));

var _isEmpty = _interopRequireDefault(require("lodash/isEmpty"));

var _translator = _interopRequireDefault(require("@pie-lib/pie-toolbox/translator"));

var _reactDom = _interopRequireDefault(require("react-dom"));

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

var translator = _translator["default"].translator;
var registered = false;
var NEWLINE_LATEX = /\\newline/g;
var REGEX = /{{response}}/gm;
var DEFAULT_KEYPAD_VARIANT = 6; // !!! If you're using Chrome but have selected the "iPad" device in Chrome Developer Tools, the navigator.userAgent string may still report as
//  Safari because Chrome on iOS actually uses the Safari rendering engine under the hood due to Apple's restrictions on third-party browser engines.
// When you select the "iPad" device in Chrome Developer Tools, you're essentially emulating the behavior of Safari on an iPad, including the user agent string.
//  Therefore, even though you're using Chrome, the user agent string will resemble that of Safari on an iPad.
// Since the regular expression /^((?!chrome|android).)*safari/i checks for the presence of "safari" in the user agent string while excluding "chrome" and "android",
//  it will return true in this case because "safari" is present in the user agent string emulated by Chrome when in iPad mode.

var IS_SAFARI = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

function generateAdditionalKeys() {
  var keyData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  return keyData.map(function (key) {
    return {
      name: key,
      latex: key,
      write: key,
      label: key
    };
  });
}

function isChildOfCurrentPieElement(child, parent) {
  var node = child;

  while (node !== null) {
    if (parent && node === parent) {
      return true;
    }

    node = node.parentNode;
  }

  return false;
}

function getKeyPadWidth() {
  var additionalKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  var equationEditor = arguments.length > 1 ? arguments[1] : undefined;
  return Math.floor(additionalKeys.length / 5) * 30 + (equationEditor === 'miscellaneous' ? 600 : 500);
}

function prepareForStatic(model, state) {
  var _ref = model || {},
      config = _ref.config,
      disabled = _ref.disabled;

  var _ref2 = config || {},
      expression = _ref2.expression,
      responses = _ref2.responses,
      printMode = _ref2.printMode,
      alwaysShowCorrect = _ref2.alwaysShowCorrect;

  if (config && expression) {
    var modelExpression = expression;

    if (state.showCorrect) {
      return responses && responses.length && responses[0].answer;
    }

    var answerBlocks = 1; // assume one at least
    // build out local state model using responses declared in expression

    return (modelExpression || '').replace(REGEX, function () {
      var answer = state.session.answers["r".concat(answerBlocks)];

      if (printMode && !alwaysShowCorrect) {
        var blankSpace = '\\ \\ '.repeat(30) + '\\newline ';
        return "\\MathQuillMathField[r".concat(answerBlocks++, "]{").concat(blankSpace.repeat(3), "}");
      }

      if (disabled) {
        return "\\embed{answerBlock}[r".concat(answerBlocks++, "]");
      }

      return "\\MathQuillMathField[r".concat(answerBlocks++, "]{").concat(answer && answer.value || '', "}");
    }).replace(NEWLINE_LATEX, '\\embed{newLine}[]');
  }
}

function parseAnswers(session, model) {
  var answers = {};

  if (model.config && model.config.expression) {
    var answerBlocks = 1; // assume one at least
    // build out local state model using responses declared in expression

    (model.config.expression || '').replace(REGEX, function () {
      answers["r".concat(answerBlocks)] = {
        value: session && session.answers && session.answers["r".concat(answerBlocks)] && session.answers["r".concat(answerBlocks)].value || ''
      };
      answerBlocks += 1;
    });
  }

  return answers;
}

var Main = /*#__PURE__*/function (_React$Component) {
  (0, _inherits2["default"])(Main, _React$Component);

  var _super = _createSuper(Main);

  function Main(props) {
    var _this;

    (0, _classCallCheck2["default"])(this, Main);
    _this = _super.call(this, props);
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleAnswerBlockDomUpdate", function () {
      var _this$props = _this.props,
          model = _this$props.model,
          classes = _this$props.classes;
      var _this$state = _this.state,
          session = _this$state.session,
          showCorrect = _this$state.showCorrect;
      var answers = session.answers;

      if (_this.root && model.disabled && !showCorrect) {
        Object.keys(answers).forEach(function (answerId) {
          var el = _this.root.querySelector("#".concat(answerId));

          var indexEl = _this.root.querySelector("#".concat(answerId, "Index")); // const correct = model.correctness && model.correctness.correct;


          if (el) {
            var MQ = _mathquill["default"].getInterface(2);

            var answer = answers[answerId];
            el.textContent = answer && answer.value || '';

            if (!model.view) {// for now, we're not going to be showing individual response correctness
              // TODO re-attach the classes once we are
              // el.parentElement.parentElement.classList.add(
              //   correct ? classes.correct : classes.incorrect
              // );
            } else {
              el.parentElement.parentElement.classList.remove(classes.correct);
              el.parentElement.parentElement.classList.remove(classes.incorrect);
            }

            MQ.StaticMath(el); // For now, we're not going to be indexing response blocks
            // TODO go back to indexing once we support individual response correctness
            // indexEl.textContent = `R${idx + 1}`;

            indexEl.textContent = 'R';
          }
        });
      }

      (0, _mathRendering.renderMath)(_this.root);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "updateAria", function () {
      var classes = _this.props.classes;

      if (_this.root) {
        // Update aria-hidden for .mq-selectable elements
        var selectableElements = _this.root.querySelectorAll('.mq-selectable');

        selectableElements.forEach(function (elem) {
          return elem.setAttribute('aria-hidden', 'true');
        }); // Update aria-label for textarea elements and add aria-describedby

        var textareaElements = _this.root.querySelectorAll('textarea');

        textareaElements.forEach(function (elem, index) {
          elem.setAttribute('aria-label', 'Enter answer.'); // Create a unique id for each instructions element

          var instructionsId = "instructions-".concat(index); // Find the parent element that contains the textarea

          var parent = elem.closest('.mq-textarea');

          if (parent) {
            // Create or find the instructions element within the parent
            var instructionsElement = parent.querySelector("#".concat(instructionsId));

            if (!instructionsElement) {
              instructionsElement = document.createElement('span');
              instructionsElement.id = instructionsId;
              instructionsElement.className = classes.srOnly;
              instructionsElement.textContent = 'This field supports both keypad and keyboard input. Use the keyboard to access and interact with the on-screen math keypad, which accepts LaTeX markup. Use the down arrow key to open the keypad and navigate its buttons. Use the escape key to close the keypad and return to the input field.';
              parent.insertBefore(instructionsElement, elem);
            }

            elem.setAttribute('aria-describedby', instructionsId);
          }
        });
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "focusFirstKeypadElement", function () {
      setTimeout(function () {
        var keypadElement = document.querySelector('[data-keypad]');

        if (keypadElement) {
          var firstButton = keypadElement.querySelector("button, [role='button']");

          if (firstButton) {
            firstButton.focus();
          }
        }
      }, 0);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "handleKeyDown", function (event, id) {
      var _this$mqStatic$inputR, _this$mqStatic$inputR2, _document$activeEleme;

      var isTrigerredFromActualPieElement = isChildOfCurrentPieElement(event.target, _this.root);
      var isAnswerInputFocused = _this.mqStatic && (_this$mqStatic$inputR = _this.mqStatic.inputRef) !== null && _this$mqStatic$inputR !== void 0 && _this$mqStatic$inputR.current ? (_this$mqStatic$inputR2 = _this.mqStatic.inputRef) === null || _this$mqStatic$inputR2 === void 0 ? void 0 : _this$mqStatic$inputR2.current.contains(document.activeElement) : ((_document$activeEleme = document.activeElement) === null || _document$activeEleme === void 0 ? void 0 : _document$activeEleme.getAttribute('aria-label')) === 'Enter answer.';
      var key = event.key,
          type = event.type;
      var isClickOrTouchEvent = type === 'click' || type === 'touchstart';

      if (isAnswerInputFocused && (key === 'ArrowDown' || isClickOrTouchEvent)) {
        if (_this.state.activeAnswerBlock !== id && isTrigerredFromActualPieElement) {
          _this.cleanupKeyDownListener();

          _this.setState({
            activeAnswerBlock: id
          }, function () {
            _this.onSubFieldFocus(id);

            if (key === 'ArrowDown') {
              _this.focusFirstKeypadElement();
            }
          });
        }
      } else if (event.key === 'Escape') {
        _this.setState({
          activeAnswerBlock: ''
        });
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onSubFieldFocus", function (id) {
      if (!_this.handleEvent) {
        _this.handleEvent = function (event) {
          _this.handleKeyDown(event, id);
        };

        document.addEventListener('keydown', _this.handleEvent);
        document.addEventListener('click', _this.handleEvent);
        document.addEventListener('touchstart', _this.handleEvent);
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "cleanupKeyDownListener", function () {
      if (_this.handleEvent) {
        document.removeEventListener('keydown', _this.handleEvent);
        document.removeEventListener('click', _this.handleEvent);
        document.removeEventListener('touchstart', _this.handleEvent);
        _this.handleEvent = null;
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onDone", function () {});
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onSimpleResponseChange", function (response) {
      _this.setState(function (state) {
        return {
          session: _objectSpread(_objectSpread({}, state.session), {}, {
            response: response
          })
        };
      }, _this.callOnSessionChange);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "toNodeData", function (data) {
      if (!data) {
        return;
      }

      var type = data.type,
          value = data.value;

      if (type === 'command' || type === 'cursor') {
        return data;
      } else if (type === 'answer') {
        return _objectSpread({
          type: 'answer'
        }, data);
      } else if (value === 'clear') {
        return {
          type: 'clear'
        };
      } else {
        return {
          type: 'write',
          value: value
        };
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "setInput", function (input) {
      _this.input = input;
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onClick", function (data) {
      var c = _this.toNodeData(data);

      if (c.type === 'clear') {
        _this.input.clear();
      } else if (c.type === 'command') {
        if (Array.isArray(c.value)) {
          c.value.forEach(function (vv) {
            _this.input.cmd(vv);
          });
        } else {
          _this.input.cmd(c.value);
        }
      } else if (c.type === 'cursor') {
        _this.input.keystroke(c.value);
      } else {
        _this.input.write(c.value);
      }

      _this.input.focus();
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "callOnSessionChange", function () {
      var onSessionChange = _this.props.onSessionChange;

      if (onSessionChange) {
        onSessionChange(_this.state.session);
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "toggleShowCorrect", function (show) {
      _this.setState({
        showCorrect: show
      }, _this.handleAnswerBlockDomUpdate);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "subFieldChanged", function (name, subfieldValue) {
      (0, _mathInput.updateSpans)();

      if (name) {
        _this.setState(function (state) {
          return {
            session: _objectSpread(_objectSpread({}, state.session), {}, {
              completeAnswer: _this.mqStatic && _this.mqStatic.mathField.latex(),
              answers: _objectSpread(_objectSpread({}, state.session.answers), {}, (0, _defineProperty2["default"])({}, name, {
                value: subfieldValue
              }))
            })
          };
        }, _this.callOnSessionChange);
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getFieldName", function (changeField, fields) {
      var answers = _this.state.session.answers;

      if (Object.keys(answers || {}).length) {
        var keys = Object.keys(answers);
        return keys.find(function (k) {
          var tf = fields[k];
          return tf && tf.id == changeField.id;
        });
      }
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onBlur", function (e) {
      var _ref3 = e || {},
          relatedTarget = _ref3.relatedTarget,
          currentTarget = _ref3.currentTarget; // our keypad is in tooltip
      // in this way we see if event was triggered from the keypad


      var isKeypadOpen = currentTarget && currentTarget.closest('[role=tooltip]');

      function getParentWithRoleTooltip(element) {
        var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
        // only run this max 16 times
        if (!element || depth >= 16) return null;
        var parent = element.offsetParent;
        if (!parent) return null;

        if (parent.getAttribute('role') === 'tooltip') {
          return parent;
        }

        return getParentWithRoleTooltip(parent, depth + 1);
      }

      function getDeepChildDataKeypad(element) {
        var _element$children;

        var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
        // only run this max 4 times
        if (!element || depth >= 4) return null;
        var child = element === null || element === void 0 ? void 0 : (_element$children = element.children) === null || _element$children === void 0 ? void 0 : _element$children[0];
        if (!child) return null;

        if (child.attributes && child.attributes['data-keypad']) {
          return child;
        }

        return getDeepChildDataKeypad(child, depth + 1);
      }

      var parentWithTooltipRole = getParentWithRoleTooltip(relatedTarget);
      var childWithDataKeypad = parentWithTooltipRole ? getDeepChildDataKeypad(parentWithTooltipRole) : null;

      if (!relatedTarget || !currentTarget || !(childWithDataKeypad !== null && childWithDataKeypad !== void 0 && childWithDataKeypad.attributes['data-keypad'])) {
        // if event was trigered from the keypad, avoid closing the keypad
        if (!isKeypadOpen) {
          _this.setState({
            activeAnswerBlock: ''
          });
        }
      } // else {
      //     // Just for debugging purpose:
      //     console.log('\n\nNew childWithDataKeypad', childWithDataKeypad);
      //
      //     if (IS_SAFARI) {
      //         // (IS_SAFARI && !relatedTarget?.offsetParent?.children[0]?.children[0]?.attributes?.['data-keypad'])
      //         console.log('What was being used', relatedTarget?.offsetParent?.children[0]?.children[0]);
      //     } else {
      //         // (!IS_SAFARI && !relatedTarget?.offsetParent?.children[0]?.attributes?.['data-keypad']) ||
      //         console.log('What was being used', relatedTarget?.offsetParent?.children[0]);
      //     }
      // }

    });
    var _model = props.model,
        _session = props.session;

    var _answers = parseAnswers(_session, _model);

    _this.state = {
      session: _objectSpread(_objectSpread({}, props.session), {}, {
        answers: _answers
      }),
      activeAnswerBlock: '',
      showCorrect: _this.props.model.config.alwaysShowCorrect || false,
      tooltipContainerRef: /*#__PURE__*/_react["default"].createRef()
    };
    return _this;
  }

  (0, _createClass2["default"])(Main, [{
    key: "UNSAFE_componentWillMount",
    value: function UNSAFE_componentWillMount() {
      var classes = this.props.classes;

      if (typeof window !== 'undefined') {
        var MQ = _mathquill["default"].getInterface(2);

        if (!registered) {
          MQ.registerEmbed('answerBlock', function (data) {
            return {
              htmlString: "<div class=\"".concat(classes.blockContainer, "\">\n                <div class=\"").concat(classes.blockResponse, "\" id=\"").concat(data, "Index\">R</div>\n                <div class=\"").concat(classes.blockMath, "\">\n                  <span id=\"").concat(data, "\"></span>\n                </div>\n              </div>"),
              text: function text() {
                return 'text';
              },
              latex: function latex() {
                return "\\embed{answerBlock}[".concat(data, "]");
              }
            };
          });
          registered = true;
        }
      }
    }
  }, {
    key: "countResponseOccurrences",
    value: function countResponseOccurrences(expression) {
      var pattern = /\{\{response\}\}/g;
      var matches = expression === null || expression === void 0 ? void 0 : expression.match(pattern);
      return matches ? matches.length : 0;
    }
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      var _this2 = this;

      var config = this.props.model.config;

      var _ref4 = nextProps.model || {},
          _ref4$config = _ref4.config,
          nextConfig = _ref4$config === void 0 ? {} : _ref4$config;

      var session = this.props.session;

      var _ref5 = nextProps || {},
          _ref5$session = _ref5.session,
          nextSession = _ref5$session === void 0 ? {} : _ref5$session; // in case session props changed in parent, we need to catch this and update local state
      // example: when env is changing in pieoneer


      if (session && nextSession && !(0, _isEqual["default"])(session.answers, nextSession.answers)) {
        this.setState({
          session: _objectSpread(_objectSpread({}, nextSession), {}, {
            answers: parseAnswers(nextSession, this.props.model)
          })
        });
      } // check if the note is the default one for prev language and change to the default one for new language
      // this check is necessary in order to diferanciate between default and authour defined note
      // and only change between languages for default ones


      if (config.note && config.language && config.language !== nextConfig.language && config.note === translator.t('mathInline.primaryCorrectWithAlternates', {
        lng: config.language
      })) {
        config.note = translator.t('mathInline.primaryCorrectWithAlternates', {
          lng: nextConfig.language
        });
      }

      if (config.env && config.env.mode !== 'evaluate' || nextConfig.env && nextConfig.env.mode !== 'evaluate') {
        this.setState(_objectSpread(_objectSpread({}, this.state.session), {}, {
          showCorrect: false
        }));
      }

      if (nextConfig.alwaysShowCorrect) {
        this.setState({
          showCorrect: true
        });
      }

      if (this.countResponseOccurrences(config.expression) < this.countResponseOccurrences(nextConfig.expression)) {
        setTimeout(function () {
          return _this2.updateAria();
        }, 100);
      }

      if (config && config.responses && config.responses.length !== nextConfig.responses.length || !config && nextConfig && nextConfig.responses || config && nextConfig && config.expression !== nextConfig.expression) {
        var newAnswers = {};
        var answers = this.state.session.answers;
        var answerBlocks = 1; // assume one at least
        // build out local state model using responses declared in expression

        (nextConfig.expression || '').replace(REGEX, function () {
          newAnswers["r".concat(answerBlocks)] = {
            value: answers && answers["r".concat(answerBlocks)] && answers["r".concat(answerBlocks)].value || ''
          };
          answerBlocks++;
        });
        this.setState(function (state) {
          return {
            session: _objectSpread(_objectSpread({}, state.session), {}, {
              completeAnswer: _this2.mqStatic && _this2.mqStatic.mathField.latex(),
              answers: newAnswers
            })
          };
        }, this.handleAnswerBlockDomUpdate);
      }
    }
  }, {
    key: "shouldComponentUpdate",
    value: function shouldComponentUpdate(nextProps, nextState) {
      var sameModel = (0, _isEqual["default"])(this.props.model, nextProps.model);
      var sameState = (0, _isEqual["default"])(this.state, nextState);
      return !sameModel || !sameState;
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this3 = this;

      this.handleAnswerBlockDomUpdate();
      this.updateAria();
      setTimeout(function () {
        return (0, _mathRendering.renderMath)(_this3.root);
      }, 100);
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      var _prevProps$model, _prevProps$model$conf, _this$props$model, _this$props$model$con;

      this.handleAnswerBlockDomUpdate();
      var prevResponseType = (_prevProps$model = prevProps.model) === null || _prevProps$model === void 0 ? void 0 : (_prevProps$model$conf = _prevProps$model.config) === null || _prevProps$model$conf === void 0 ? void 0 : _prevProps$model$conf.responseType;
      var currentResponseType = (_this$props$model = this.props.model) === null || _this$props$model === void 0 ? void 0 : (_this$props$model$con = _this$props$model.config) === null || _this$props$model$con === void 0 ? void 0 : _this$props$model$con.responseType;

      if (prevResponseType !== currentResponseType) {
        this.updateAria();
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      if (this.cleanupKeyDownListener) {
        this.cleanupKeyDownListener();
      }
    }
  }, {
    key: "setTooltipRef",
    value: function setTooltipRef(ref) {
      // Safari Hack: https://stackoverflow.com/a/42764495/5757635
      setTimeout(function () {
        if (ref && IS_SAFARI) {
          var div = document.querySelector("[role='tooltip']");

          if (div) {
            var el = div.firstChild;
            el.setAttribute('tabindex', '-1');
          }
        }
      }, 1);
    }
  }, {
    key: "render",
    value: function render() {
      var _this4 = this,
          _cx;

      var _this$props2 = this.props,
          model = _this$props2.model,
          classes = _this$props2.classes;
      var _this$state2 = this.state,
          activeAnswerBlock = _this$state2.activeAnswerBlock,
          showCorrect = _this$state2.showCorrect,
          session = _this$state2.session,
          tooltipContainerRef = _this$state2.tooltipContainerRef;

      var _ref6 = model || {},
          config = _ref6.config,
          correctness = _ref6.correctness,
          disabled = _ref6.disabled,
          extraCSSRules = _ref6.extraCSSRules,
          view = _ref6.view,
          teacherInstructions = _ref6.teacherInstructions,
          rationale = _ref6.rationale,
          feedback = _ref6.feedback,
          animationsDisabled = _ref6.animationsDisabled,
          printMode = _ref6.printMode,
          alwaysShowCorrect = _ref6.alwaysShowCorrect,
          language = _ref6.language;

      if (!config) {
        return null;
      }

      var _ref7 = config || {},
          showNote = _ref7.showNote,
          note = _ref7.note,
          prompt = _ref7.prompt,
          responses = _ref7.responses,
          responseType = _ref7.responseType,
          equationEditor = _ref7.equationEditor,
          customKeys = _ref7.customKeys,
          id = _ref7.id,
          _ref7$env = _ref7.env;

      _ref7$env = _ref7$env === void 0 ? {} : _ref7$env;
      var mode = _ref7$env.mode,
          role = _ref7$env.role;
      var displayNote = (showCorrect || mode === 'view' && role === 'instructor') && showNote && note;
      var emptyResponse = (0, _isEmpty["default"])(responses);
      var showCorrectAnswerToggle = !emptyResponse && correctness && correctness.correctness !== 'correct';
      var tooltipModeEnabled = disabled && correctness;
      var additionalKeys = generateAdditionalKeys(customKeys);
      var correct = correctness && correctness.correct;
      var staticLatex = prepareForStatic(model, this.state) || '';
      var viewMode = disabled && !correctness;
      var studentPrintMode = printMode && !alwaysShowCorrect;
      var showRationale = rationale && ((0, _renderUi.hasText)(rationale) || (0, _renderUi.hasMedia)(rationale));
      var showTeacherInstructions = teacherInstructions && ((0, _renderUi.hasText)(teacherInstructions) || (0, _renderUi.hasMedia)(teacherInstructions));

      var printView = /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.printContainer
      }, /*#__PURE__*/_react["default"].createElement(_mathInput.mq.Static, {
        className: classes["static"],
        ref: function ref(mqStatic) {
          if (mqStatic) _this4.mqStatic = mqStatic;
        },
        latex: staticLatex,
        onSubFieldChange: this.subFieldChanged,
        getFieldName: this.getFieldName,
        setInput: this.setInput,
        onSubFieldFocus: this.onSubFieldFocus,
        onBlur: this.onBlur
      }));

      var midContent = /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.main
      }, mode === 'gather' && /*#__PURE__*/_react["default"].createElement("h2", {
        className: classes.srOnly
      }, "Math Equation Response Question"), viewMode && showTeacherInstructions && (!animationsDisabled ? /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
        className: classes.collapsible,
        labels: {
          hidden: 'Show Teacher Instructions',
          visible: 'Hide Teacher Instructions'
        }
      }, /*#__PURE__*/_react["default"].createElement("div", {
        dangerouslySetInnerHTML: {
          __html: teacherInstructions
        }
      })) : /*#__PURE__*/_react["default"].createElement("div", {
        dangerouslySetInnerHTML: {
          __html: teacherInstructions
        }
      })), prompt && /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.promptContainer
      }, /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
        prompt: prompt
      })), studentPrintMode ? printView : /*#__PURE__*/_react["default"].createElement(_renderUi.Readable, {
        "false": true
      }, /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.inputAndKeypadContainer,
        tabIndex: 0
      }, responseType === _utils.ResponseTypes.simple && /*#__PURE__*/_react["default"].createElement(_simpleQuestionBlock["default"], {
        onSimpleResponseChange: this.onSimpleResponseChange,
        showCorrect: showCorrect,
        emptyResponse: emptyResponse,
        model: model,
        session: session,
        onSubFieldFocus: this.onSubFieldFocus,
        showKeypad: !!activeAnswerBlock
      }), responseType === _utils.ResponseTypes.advanced && /*#__PURE__*/_react["default"].createElement("div", {
        ref: tooltipContainerRef,
        className: (0, _classnames["default"])(classes.expression, (_cx = {}, (0, _defineProperty2["default"])(_cx, classes.incorrect, !emptyResponse && !correct && !showCorrect), (0, _defineProperty2["default"])(_cx, classes.correct, !emptyResponse && (correct || showCorrect)), (0, _defineProperty2["default"])(_cx, classes.showCorrectness, !emptyResponse && disabled && correctness && !view), (0, _defineProperty2["default"])(_cx, classes.correctAnswerShown, showCorrect), (0, _defineProperty2["default"])(_cx, classes.printCorrect, printMode && alwaysShowCorrect), _cx))
      }, /*#__PURE__*/_react["default"].createElement(_Tooltip["default"], {
        ref: function ref(_ref8) {
          return _this4.setTooltipRef(_ref8);
        },
        enterTouchDelay: 0,
        interactive: true,
        open: !!activeAnswerBlock,
        classes: {
          tooltip: classes.keypadTooltip,
          popper: classes.keypadTooltipPopper
        },
        PopperProps: {
          container: (tooltipContainerRef === null || tooltipContainerRef === void 0 ? void 0 : tooltipContainerRef.current) || undefined,
          placement: 'bottom-start',
          modifiers: {
            preventOverflow: {
              enabled: true,
              boundariesElement: 'body'
            },
            flip: {
              enabled: false
            }
          }
        },
        title: Object.keys(session.answers).map(function (answerId) {
          return answerId === activeAnswerBlock && !(showCorrect || disabled) && /*#__PURE__*/_react["default"].createElement("div", {
            "data-keypad": true,
            key: answerId,
            className: classes.responseContainer,
            style: {
              // marginTop: this.mqStatic && this.mqStatic.input.offsetHeight - 20,
              width: getKeyPadWidth(additionalKeys, equationEditor)
            }
          }, /*#__PURE__*/_react["default"].createElement(_mathInput.HorizontalKeypad, {
            additionalKeys: additionalKeys,
            mode: equationEditor || DEFAULT_KEYPAD_VARIANT,
            onClick: _this4.onClick
          })) || null;
        })
      }, /*#__PURE__*/_react["default"].createElement(_mathInput.mq.Static, {
        className: classes["static"],
        ref: function ref(mqStatic) {
          if (mqStatic) _this4.mqStatic = mqStatic;
        },
        latex: staticLatex,
        onSubFieldChange: this.subFieldChanged,
        getFieldName: this.getFieldName,
        setInput: this.setInput,
        onSubFieldFocus: this.onSubFieldFocus,
        onBlur: this.onBlur
      }))))), viewMode && displayNote && /*#__PURE__*/_react["default"].createElement("div", {
        className: classes.note,
        dangerouslySetInnerHTML: {
          __html: "<strong>Note:</strong> ".concat(note)
        }
      }), viewMode && showRationale && (!animationsDisabled ? /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
        labels: {
          hidden: 'Show Rationale',
          visible: 'Hide Rationale'
        }
      }, /*#__PURE__*/_react["default"].createElement("div", {
        dangerouslySetInnerHTML: {
          __html: rationale
        }
      })) : /*#__PURE__*/_react["default"].createElement("div", {
        dangerouslySetInnerHTML: {
          __html: rationale
        }
      })));

      if (tooltipModeEnabled && (showCorrectAnswerToggle || showTeacherInstructions || showRationale || feedback)) {
        return /*#__PURE__*/_react["default"].createElement(_renderUi.UiLayout, {
          extraCSSRules: extraCSSRules
        }, /*#__PURE__*/_react["default"].createElement(_Tooltip["default"], {
          interactive: true,
          enterTouchDelay: 0,
          classes: {
            tooltip: classes.tooltip,
            popper: classes.tooltipPopper
          },
          title: /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement("div", {
            className: classes.main
          }, showCorrectAnswerToggle && /*#__PURE__*/_react["default"].createElement(_correctAnswerToggle.CorrectAnswerToggle, {
            language: language,
            className: classes.toggle,
            show: true,
            toggled: showCorrect,
            onToggle: this.toggleShowCorrect
          })), showTeacherInstructions && /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
            className: classes.collapsible,
            key: "collapsible-teacher-instructions",
            labels: {
              hidden: 'Show Teacher Instructions',
              visible: 'Hide Teacher Instructions'
            }
          }, /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
            prompt: teacherInstructions
          })), displayNote && (0, _renderUi.hasText)(note) && /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
            className: classes.collapsible,
            key: "collapsible-note",
            labels: {
              hidden: translator.t('common:showNote', {
                lng: language
              }),
              visible: translator.t('common:hideNote', {
                lng: language
              })
            }
          }, /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
            prompt: note
          })), showRationale && /*#__PURE__*/_react["default"].createElement(_renderUi.Collapsible, {
            className: classes.collapsible,
            key: "collapsible-rationale",
            labels: {
              hidden: 'Show Rationale',
              visible: 'Hide Rationale'
            }
          }, /*#__PURE__*/_react["default"].createElement(_renderUi.PreviewPrompt, {
            prompt: rationale
          })), feedback && /*#__PURE__*/_react["default"].createElement(_renderUi.Feedback, {
            correctness: correctness.correctness,
            feedback: feedback
          }))
        }, /*#__PURE__*/_react["default"].createElement("div", {
          className: classes.mainContainer,
          ref: function ref(r) {
            return _this4.root = r || _this4.root;
          }
        }, midContent)));
      }

      return /*#__PURE__*/_react["default"].createElement(_renderUi.UiLayout, {
        id: id,
        extraCSSRules: extraCSSRules,
        className: classes.mainContainer,
        ref: function ref(r) {
          // eslint-disable-next-line react/no-find-dom-node
          var domNode = _reactDom["default"].findDOMNode(r);

          _this4.root = domNode || _this4.root;
        }
      }, midContent);
    }
  }]);
  return Main;
}(_react["default"].Component);

exports.Main = Main;
(0, _defineProperty2["default"])(Main, "propTypes", {
  classes: _propTypes["default"].object,
  session: _propTypes["default"].object.isRequired,
  onSessionChange: _propTypes["default"].func,
  model: _propTypes["default"].object.isRequired
});

var styles = function styles(theme) {
  return {
    mainContainer: {
      color: _renderUi.color.text(),
      backgroundColor: _renderUi.color.background(),
      display: 'inline-block'
    },
    tooltip: {
      background: "".concat(_renderUi.color.primaryLight(), " !important"),
      color: _renderUi.color.text(),
      padding: theme.spacing.unit * 2,
      border: "1px solid ".concat(_renderUi.color.secondary()),
      fontSize: '16px',
      '& :not(.MathJax) > table tr': {
        '&:nth-child(2n)': {
          backgroundColor: 'unset !important'
        }
      }
    },
    tooltipPopper: {
      opacity: 1
    },
    keypadTooltip: {
      fontSize: 'initial',
      background: 'transparent',
      width: '600px',
      marginTop: 0,
      paddingTop: 0
    },
    keypadTooltipPopper: {
      background: 'transparent',
      width: '650px',
      opacity: 1
    },
    promptContainer: {
      marginBottom: theme.spacing.unit * 2
    },
    main: {
      width: '100%',
      position: 'relative',
      backgroundColor: _renderUi.color.background(),
      color: _renderUi.color.text()
    },
    title: {
      fontSize: '1.1rem',
      display: 'block',
      marginTop: theme.spacing.unit * 2,
      marginBottom: theme.spacing.unit
    },
    note: {
      paddingBottom: theme.spacing.unit * 2
    },
    collapsible: {
      marginBottom: theme.spacing.unit * 2
    },
    responseContainer: {
      zIndex: 10,
      // position: 'absolute',
      // right: 0,
      minWidth: '400px',
      marginTop: theme.spacing.unit * 2
    },
    expression: {
      maxWidth: 'fit-content',
      padding: theme.spacing.unit / 4,
      '& > .mq-math-mode': {
        '& > .mq-root-block': {
          // PD-4803 unset padding as events are not correctly propagated in the proximity of math input
          paddingRight: '0 !important',
          paddingLeft: '0 !important',
          '& > .mq-editable-field': {
            minWidth: '10px',
            padding: theme.spacing.unit / 4
          }
        },
        '& sup': {
          top: 0
        }
      }
    },
    "static": {
      '& > .mq-root-block': {
        '& > .mq-editable-field': {
          borderColor: _renderUi.color.text()
        }
      }
    },
    inputAndKeypadContainer: {
      position: 'relative',
      '& .mq-overarrow-inner': {
        border: 'none !important',
        padding: '0 !important'
      },
      '& .mq-overarrow-inner-right': {
        display: 'none !important'
      },
      '& .mq-overarrow-inner-left': {
        display: 'none !important'
      },
      '& .mq-overarrow.mq-arrow-both': {
        minWidth: '1.23em',
        '& *': {
          lineHeight: '1 !important'
        },
        '&:before': {
          top: '-0.4em',
          left: '-1px'
        },
        '&:after': {
          top: '-2.4em',
          right: '-1px'
        },
        '&.mq-empty:after': {
          top: '-0.45em'
        }
      },
      '& .mq-overarrow.mq-arrow-right': {
        '&:before': {
          top: '-0.4em',
          right: '-1px'
        }
      },
      '& .mq-longdiv-inner': {
        borderTop: '1px solid !important',
        paddingTop: '1.5px !important'
      },
      '& .mq-parallelogram': {
        lineHeight: 0.85
      }
    },
    showCorrectness: {
      border: '2px solid'
    },
    correctAnswerShown: {
      padding: theme.spacing.unit,
      letterSpacing: '0.5px'
    },
    printCorrect: {
      border: "2px solid ".concat(_renderUi.color.correct(), " !important")
    },
    correct: {
      borderColor: "".concat(_renderUi.color.correct(), " !important")
    },
    incorrect: {
      borderColor: "".concat(_renderUi.color.incorrect(), " !important")
    },
    blockContainer: {
      margin: "".concat(theme.spacing.unit, "px !important"),
      display: 'inline-flex',
      border: '2px solid grey !important'
    },
    blockResponse: {
      color: 'grey',
      background: theme.palette.grey['A100'],
      fontSize: '0.8rem !important',
      padding: "".concat(theme.spacing.unit / 2, "px !important"),
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      borderRight: "2px solid ".concat(_renderUi.color.disabled(), " !important"),
      flexShrink: 0,
      flexGrow: 0,
      flexBasis: 'auto' // take only the space needed for content + padding

    },
    toggle: {
      color: _renderUi.color.text(),
      marginBottom: theme.spacing.unit * 2
    },
    blockMath: {
      color: _renderUi.color.text(),
      backgroundColor: _renderUi.color.background(),
      padding: "".concat(theme.spacing.unit / 2, "px !important"),
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      flexGrow: 1,
      // take all the remaining space
      '& > .mq-math-mode': {
        '& > .mq-hasCursor': {
          '& > .mq-cursor': {
            display: 'none'
          }
        }
      }
    },
    printContainer: {
      marginBottom: theme.spacing.unit,
      pointerEvents: 'none'
    },
    srOnly: {
      position: 'absolute',
      left: '-10000px',
      top: 'auto',
      width: '1px',
      height: '1px',
      overflow: 'hidden'
    }
  };
};

var _default = (0, _styles.withStyles)(styles)(Main);

exports["default"] = _default;
//# sourceMappingURL=main.js.map