'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.messageForSubmitModal = exports.nextQuestion = exports.submitStudentAccessCode = exports.makeSessionItemCall = exports.getResumeData = undefined;

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');

var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);

var _default_enGB_number = Intl.NumberFormat('en-GB', { style: 'decimal' }).format; // =============================================
// =============================================

//  this file is in charge of coordinating the
//  dispatching of actions necessary to interact
//  with quizzes via the api for taking purposes

// =============================================
// =============================================

exports.confirmSessionStartPage = confirmSessionStartPage;
exports.newQuizTakingSession = newQuizTakingSession;
exports.onQuizSessionReadyForTaking = onQuizSessionReadyForTaking;
exports.showSubmitConfirmModal = showSubmitConfirmModal;
exports.closeSubmitConfirmModal = closeSubmitConfirmModal;
exports.submitQuiz = submitQuiz;
exports.postQuizSession = postQuizSession;
exports.getTimeRemaining = getTimeRemaining;
exports.recordQuizTime = recordQuizTime;
exports.authenticateLearnosity = authenticateLearnosity;

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _partial = require('lodash/partial');

var _partial2 = _interopRequireDefault(_partial);

var _immutable = require('immutable');

var _humps = require('humps');

var _formatMessage = require('../../common/format-message');

var _formatMessage2 = _interopRequireDefault(_formatMessage);

var _noop = require('../../common/util/noop');

var _noop2 = _interopRequireDefault(_noop);

var _alerts = require('../../common/actions/alerts');

var _Item = require('../../common/records/Item');

var _Item2 = _interopRequireDefault(_Item);

var _learnosityLoader = require('quiz-interactions/lib/util/learnosity-loader');

var _learnosityLoader2 = _interopRequireDefault(_learnosityLoader);

var _constants = require('../../constants');

var _ui = require('../../common/actions/ui');

var uiActions = _interopRequireWildcard(_ui);

var _quizSessions = require('../../common/api/quizSessions');

var _quizSessions2 = require('../../common/actions/quizSessions');

var _callHandlers = require('../../common/api/callHandlers');

var _modal = require('../../common/actions/modal');

var modalActions = _interopRequireWildcard(_modal);

var _taking = require('../../common/actions/taking');

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

var _Fetcher2 = _interopRequireDefault(_Fetcher);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var getQuizSessionConfig = function getQuizSessionConfig(quizSession) {
  // these should be handled by existing functions
  var oneQuestionAtATime = quizSession.isOneQuestionAtATime();
  var allowBacktracking = quizSession.allowBacktracking;
  var useSessionItemIndex = !oneQuestionAtATime || allowBacktracking;
  return { oneQuestionAtATime: oneQuestionAtATime, allowBacktracking: allowBacktracking, useSessionItemIndex: useSessionItemIndex };
};

var getResumeData = exports.getResumeData = function getResumeData(quizSessionId) {
  return function (dispatch) {
    var responseCb = function responseCb(resumeData) {
      return dispatch((0, _callHandlers.handleResumeDataResponse)(resumeData, quizSessionId));
    };

    return (0, _quizSessions.fetchResumeData)(quizSessionId, responseCb);
  };
};

var makeSessionItemCall = exports.makeSessionItemCall = function makeSessionItemCall(quizSession) {
  var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _quizSessions2.getSessionItems;
  var next = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : nextQuestion;

  return function (dispatch) {
    var action = getQuizSessionConfig(quizSession).useSessionItemIndex ? index(quizSession.id) : next(quizSession.id, false, false, null, null, null);

    return dispatch(action);
  };
};

var submitStudentAccessCode = exports.submitStudentAccessCode = function submitStudentAccessCode(quizSessionId, accessCode) {
  return function (dispatch) {
    var responseCb = function responseCb(sessionData) {
      dispatch(uiActions.set(_constants.STUDENT_ACCESS_CODE_STATUS, sessionData.accepted_student_access_code));
      if (sessionData.accepted_student_access_code) {
        dispatch((0, _alerts.screenreaderNotification)('Access code successful. You may now begin this assessment'));
      } else {
        dispatch((0, _alerts.screenreaderNotification)('Invalid access code'));
      }
      return dispatch((0, _callHandlers.handleQuizSessionResponse)(sessionData, quizSessionId));
    };

    return (0, _quizSessions.submitStudentAccessCode)(quizSessionId, accessCode, responseCb);
  };
};

// ====================================
// OQAAT no backtracking call
// ====================================
var noBacktrackingNextQuestion = function noBacktrackingNextQuestion(quizSessionId, itemId, userResponse, largeFormatResponse, submit) {
  return function (dispatch) {
    var params = {};
    if (itemId) {
      params.body = JSON.stringify({
        sessionItemResponse: {
          itemId: itemId,
          userResponse: userResponse,
          largeFormatResponse: largeFormatResponse
        }
      });
    }
    var responseCb = function responseCb(nextItem) {
      if (nextItem) {
        dispatch([(0, _callHandlers.handleSessionItemsResponse)([nextItem], quizSessionId), (0, _taking.setCurrentSessionItemPosition)(nextItem.position)]);
      } else {
        submit();
      }
    };

    return (0, _quizSessions.singleResponseSubmit)(quizSessionId, params, responseCb);
  };
};

// ====================================
// OQAAT no backtracking call
// ====================================
var nextQuestion = exports.nextQuestion = function nextQuestion(quizSessionId, allowBacktracking, currentQuestionIsLast, itemId, userResponse, largeFormatResponse) {
  var submit = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : submitQuiz;

  if (allowBacktracking) {
    return function (dispatch) {
      var action = currentQuestionIsLast ? submit(quizSessionId) : (0, _taking.backtrackingNextQuestion)();

      if (action) dispatch(action);
    };
  } else {
    return noBacktrackingNextQuestion(quizSessionId, itemId, userResponse, largeFormatResponse, submit);
  }
};

// ====================================
// load up the quiz session for the taking page
// ====================================
function confirmSessionStartPage(quizSessionId) {
  var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _noop2.default;
  var authRedirectCb = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _noop2.default;

  return function (dispatch) {
    return (0, _quizSessions.fetchQuizSession)(quizSessionId, (0, _partial2.default)(_quizSessions2.handleQuizSessionFetch, dispatch)).then(cb).catch(function (e) {
      if (e.response.status === 403) {
        authRedirectCb();
      }
    });
  };
}

// ====================================
// fetch the data for a new quiz_session
// ====================================
function newQuizTakingSession(quizSessionId) {
  var cb = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _noop2.default;
  var authRedirectCb = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _noop2.default;

  return function (dispatch) {
    return (0, _quizSessions.takeQuizSession)(quizSessionId, (0, _partial2.default)(_quizSessions2.handleQuizSessionFetch, dispatch)).then(cb).catch(function (e) {
      if (e.response.status === 403) {
        authRedirectCb();
      }
    });
  };
}

function onQuizSessionReadyForTaking(quizSession) {
  return function (dispatch) {
    dispatch([makeSessionItemCall(quizSession), getResumeData(quizSession.id), (0, _taking.sessionStartOrResumeEvent)(navigator.userAgent), (0, _taking.updateQuizSessionStatusOnPageLoad)(quizSession.status)]);
  };
}

// ====================================
// show submit confirmation modal
// ====================================

var messageForSubmitModal = exports.messageForSubmitModal = function messageForSubmitModal(positions) {
  if (!positions || positions.length === 0) {
    return 'Upon submission you will not be able to change your answers. Are you ready to submit?';
  }

  if (positions.length >= 10) {
    return 'Multiple questions have not been answered. Upon submission you will not be able to change your answers. Are you ready to submit?';
  }

  return _react2.default.createElement(
    'div',
    null,
    _react2.default.createElement(
      'p',
      null,
      'The following questions have not been answered:'
    ),
    _react2.default.createElement(
      'ul',
      null,
      positions.map(function (position) {
        return _react2.default.createElement(
          'li',
          { key: position },
          'Question ' + _default_enGB_number(position)
        );
      })
    ),
    _react2.default.createElement(
      'p',
      null,
      'Upon submission you will not be able to change your answers. Are you ready to submit?'
    )
  );
};

var __getResponseForSessionItem = function __getResponseForSessionItem(sessionItem, responses) {
  var resp = responses.find(function (r) {
    return r.get('position') === sessionItem.get('position');
  });
  return resp && resp.get('userResponse').toJS();
};

var __remainingQuestionPositions = function __remainingQuestionPositions(sessionItems, responses) {
  return sessionItems.toList().sortBy(function (si) {
    return si.get('position');
  }).filterNot(function (si) {
    var item = new _Item2.default(si.get('item'));
    var itemUserResponse = __getResponseForSessionItem(si, responses);
    return item.hasResponse(itemUserResponse);
  }).map(function (si) {
    return si.get('position');
  }).toSet().toJS();
};

function showSubmitConfirmModal(quizSessionId) {
  var onSubmitQuizSession = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _noop2.default;

  return function (dispatch, getState) {
    var needResponse = getQuestionsNeedingAResponse(getState(), quizSessionId);
    var title = titleForSubmitModal(needResponse);
    var message = messageForSubmitModal(needResponse);
    var modalAction = modalActions.withConfirm(function () {
      return dispatch(postQuizSession(quizSessionId, onSubmitQuizSession));
    }, {
      title: title,
      text: message,
      continueText: 'Submit',
      cancelText: 'Cancel'
    });

    return dispatch(modalAction);
  };
}

function closeSubmitConfirmModal(quizSessionId) {
  return function (dispatch, getState) {
    var needResponse = getQuestionsNeedingAResponse(getState(), quizSessionId);
    var title = titleForSubmitModal(needResponse);
    return dispatch(modalActions.closeModal(title));
  };
}

function titleForSubmitModal(needResponse) {
  return needResponse.length > 0 ? 'Unanswered questions!' : 'Confirm submission';
}

// ==============================================
// check for unanswered questions or override
// ==============================================

function submitQuiz(quizSessionId) {
  var onSubmitQuizSession = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _noop2.default;
  var overrideConfirmation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

  return function (dispatch) {
    if (overrideConfirmation) {
      return dispatch(postQuizSession(quizSessionId, onSubmitQuizSession));
    } else {
      return dispatch(showSubmitConfirmModal(quizSessionId, onSubmitQuizSession));
    }
  };
}

function getQuestionsNeedingAResponse(state, quizSessionId) {
  var responses = state.getIn(['taking', 'responses'], (0, _immutable.Map)());
  var sessionItems = state.get('sessionItems', (0, _immutable.Map)()).filter(function (record) {
    return record.get('quizSessionId') === quizSessionId;
  });

  return __remainingQuestionPositions(sessionItems, responses);
}

// ====================================
// submit the data for the quiz
// ====================================

function postQuizSession(quizSessionId) {
  var onSubmitQuizSession = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _noop2.default;

  return function (dispatch, getState) {
    var submitFlag = getState().getIn(['taking', 'submitFlag']);
    if (!submitFlag) {
      dispatch((0, _taking.updateQuizSubmitFlag)(true));
      var takingResponses = getState().getIn(['taking', 'responses'], (0, _immutable.Map)()).valueSeq().toJS();

      var params = {
        body: JSON.stringify({ session_item_responses: takingResponses })
      };

      var submitQuizSessionEventAction = (0, _taking.submitQuizSessionEvent)();
      var responseCb = function responseCb() {
        dispatch((0, _alerts.screenreaderNotification)('Quiz submitted'));
        onSubmitQuizSession();
        dispatch(submitQuizSessionEventAction);
      };
      return (0, _quizSessions.submitQuizSession)(quizSessionId, params, responseCb);
    }
  };
}

// ====================================
//  getting the remaining time
// ====================================

function getTimeRemaining(quizSessionId, cb) {
  return function (dispatch) {
    return (0, _quizSessions.fetchTime)(quizSessionId, function (result) {
      return cb((0, _humps.camelizeKeys)(result));
    });
  };
}

// ====================================
//  tracking time taken
// ====================================

function recordQuizTime(quizSessionId, cb) {
  return function (dispatch) {
    return (0, _quizSessions.recordTime)(quizSessionId, function (result) {
      return cb((0, _humps.camelizeKeys)(result));
    });
  };
}

// ====================================
//  authenticate the app for using learnosity tools (i.e. Calculator)
// ====================================

// Cache the questionsApp since Learnosity only fires the readyListener the first time init is called
var promise = void 0;
function authenticateLearnosity(quizSessionId) {
  if (promise) {
    return promise;
  }

  promise = new Promise(function (resolve, reject) {
    var f = new _Fetcher2.default();
    Promise.all([(0, _learnosityLoader2.default)(), f.post('/api/quiz_sessions/' + quizSessionId + '/learnosity_authentication?domain=' + window.location.hostname)]).then(function (_ref) {
      var _ref2 = (0, _slicedToArray3.default)(_ref, 2),
          app = _ref2[0],
          response = _ref2[1];

      var questionsApp = app.init(response, {
        errorListener: function errorListener(e) {
          promise = null;
          reject(e);
        },
        readyListener: function readyListener() {
          resolve(questionsApp);
        }
      });
    }).catch(function (e) {
      promise = null;
      reject(e);
    });
  });

  return promise;
}