'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.transitionRecord = exports.revertRecord = exports.setFieldValue = exports.moveFieldValue = exports.deleteFieldValue = exports.addFieldInstance = exports.saveRecord = exports.createNewRecord = exports.readRecord = exports.validateRecordData = exports.validateFieldValue = exports.VALIDATION_PASSED = exports.VALIDATION_FAILED = exports.REVERT_RECORD = exports.SET_FIELD_VALUE = exports.MOVE_FIELD_VALUE = exports.DELETE_FIELD_VALUE = exports.ADD_FIELD_INSTANCE = exports.RECORD_TRANSITION_REJECTED = exports.RECORD_TRANSITION_FULFILLED = exports.RECORD_TRANSITION_STARTED = exports.RECORD_SAVE_REJECTED = exports.RECORD_SAVE_FULFILLED = exports.RECORD_SAVE_STARTED = exports.RECORD_READ_REJECTED = exports.RECORD_READ_FULFILLED = exports.RECORD_READ_STARTED = exports.CREATE_NEW_RECORD = undefined;

var _reactIntl = require('react-intl');

var _get = require('lodash/get');

var _get2 = _interopRequireDefault(_get);

var _cspace = require('./cspace');

var _cspace2 = _interopRequireDefault(_cspace);

var _notificationHelpers = require('../helpers/notificationHelpers');

var _notificationHelpers2 = _interopRequireDefault(_notificationHelpers);

var _getErrorDescription = require('../helpers/getErrorDescription');

var _getErrorDescription2 = _interopRequireDefault(_getErrorDescription);

var _notification = require('./notification');

var _reducers = require('../reducers');

var _configHelpers = require('../helpers/configHelpers');

var _recordDataHelpers = require('../helpers/recordDataHelpers');

var _errorCodes = require('../constants/errorCodes');

var _notificationStatusCodes = require('../constants/notificationStatusCodes');

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

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /* global window */

var saveMessages = (0, _reactIntl.defineMessages)({
  saving: {
    'id': 'action.record.saving',
    'defaultMessage': '{hasTitle, select, yes {Saving {title}\u2026} other {Saving record\u2026}}'
  },
  errorSaving: {
    'id': 'action.record.errorSaving',
    'defaultMessage': '{hasTitle, select, yes {Error saving {title}: {error}} other {Error saving record: {error}}}'
  },
  saved: {
    'id': 'action.record.saved',
    'defaultMessage': '{hasTitle, select, yes {Saved {title}} other {Saved record}}'
  }
});

var transitionMessages = {
  delete: (0, _reactIntl.defineMessages)({
    transitioning: {
      'id': 'action.record.transition.delete.transitioning',
      'defaultMessage': '{hasTitle, select, yes {Deleting {title}\u2026} other {Deleting record\u2026}}'
    },
    errorTransitioning: {
      'id': 'action.record.transition.delete.errorTransitioning',
      'defaultMessage': '{hasTitle, select, yes {Error deleting {title}: {error}} other {Error deleting record: {error}}}'
    },
    transitioned: {
      'id': 'action.record.transition.delete.transitioned',
      'defaultMessage': '{hasTitle, select, yes {Deleted {title}} other {Deleted record}}'
    }
  })
};

var CREATE_NEW_RECORD = exports.CREATE_NEW_RECORD = 'CREATE_NEW_RECORD';
var RECORD_READ_STARTED = exports.RECORD_READ_STARTED = 'RECORD_READ_STARTED';
var RECORD_READ_FULFILLED = exports.RECORD_READ_FULFILLED = 'RECORD_READ_FULFILLED';
var RECORD_READ_REJECTED = exports.RECORD_READ_REJECTED = 'RECORD_READ_REJECTED';
var RECORD_SAVE_STARTED = exports.RECORD_SAVE_STARTED = 'RECORD_SAVE_STARTED';
var RECORD_SAVE_FULFILLED = exports.RECORD_SAVE_FULFILLED = 'RECORD_SAVE_FULFILLED';
var RECORD_SAVE_REJECTED = exports.RECORD_SAVE_REJECTED = 'RECORD_SAVE_REJECTED';
var RECORD_TRANSITION_STARTED = exports.RECORD_TRANSITION_STARTED = 'RECORD_TRANSITION_STARTED';
var RECORD_TRANSITION_FULFILLED = exports.RECORD_TRANSITION_FULFILLED = 'RECORD_TRANSITION_FULFILLED';
var RECORD_TRANSITION_REJECTED = exports.RECORD_TRANSITION_REJECTED = 'RECORD_TRANSITION_REJECTED';
var ADD_FIELD_INSTANCE = exports.ADD_FIELD_INSTANCE = 'ADD_FIELD_INSTANCE';
var DELETE_FIELD_VALUE = exports.DELETE_FIELD_VALUE = 'DELETE_FIELD_VALUE';
var MOVE_FIELD_VALUE = exports.MOVE_FIELD_VALUE = 'MOVE_FIELD_VALUE';
var SET_FIELD_VALUE = exports.SET_FIELD_VALUE = 'SET_FIELD_VALUE';
var REVERT_RECORD = exports.REVERT_RECORD = 'REVERT_RECORD';
var VALIDATION_FAILED = exports.VALIDATION_FAILED = 'VALIDATION_FAILED';
var VALIDATION_PASSED = exports.VALIDATION_PASSED = 'VALIDATION_PASSED';

var validateFieldValue = exports.validateFieldValue = function validateFieldValue(recordTypeConfig, csid, path, value) {
  return function (dispatch, getState) {
    var fieldDescriptor = (0, _get2.default)(recordTypeConfig, ['fields'].concat(_toConsumableArray((0, _configHelpers.dataPathToFieldDescriptorPath)(path))));
    var recordData = (0, _reducers.getRecordData)(getState(), csid);

    return (0, _recordDataHelpers.validateField)(value, [], recordData, fieldDescriptor, true).then(function (errors) {
      if (errors) {
        dispatch({
          type: VALIDATION_FAILED,
          payload: errors,
          meta: {
            csid: csid,
            path: path
          }
        });

        dispatch((0, _notification.showValidationNotification)(recordTypeConfig.name, csid));
      } else {
        dispatch({
          type: VALIDATION_PASSED,
          meta: {
            csid: csid,
            path: path
          }
        });

        dispatch((0, _notification.removeValidationNotification)());
      }
    });
  };
};

var validateRecordData = exports.validateRecordData = function validateRecordData(recordTypeConfig, csid) {
  return function (dispatch, getState) {
    var recordData = (0, _reducers.getRecordData)(getState(), csid);

    return dispatch(validateFieldValue(recordTypeConfig, csid, [], recordData));
  };
};

var doRead = function doRead(recordTypeConfig, vocabularyConfig, csid) {
  var recordServicePath = recordTypeConfig.serviceConfig.servicePath;

  var vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null;

  var pathParts = [recordServicePath];

  if (vocabularyServicePath) {
    pathParts.push(vocabularyServicePath);
    pathParts.push('items');
  }

  pathParts.push(csid);

  var path = pathParts.join('/');

  var config = {
    params: {
      showRelations: true,
      wf_deleted: false
    }
  };

  return (0, _cspace2.default)().read(path, config);
};

var readRecord = exports.readRecord = function readRecord(recordTypeConfig, vocabularyConfig, csid) {
  return function (dispatch, getState) {
    if ((0, _reducers.isRecordReadPending)(getState(), csid) || (0, _reducers.getRecordData)(getState(), csid)) {
      // We already have data for this record, or a request is already pending. Do nothing.

      return null;
    }

    dispatch({
      type: RECORD_READ_STARTED,
      meta: {
        recordTypeConfig: recordTypeConfig,
        csid: csid
      }
    });

    return doRead(recordTypeConfig, vocabularyConfig, csid).then(function (response) {
      return dispatch({
        type: RECORD_READ_FULFILLED,
        payload: response,
        meta: {
          recordTypeConfig: recordTypeConfig,
          csid: csid
        }
      });
    }).catch(function (error) {
      return dispatch({
        type: RECORD_READ_REJECTED,
        payload: {
          code: _errorCodes.ERR_API,
          error: error
        },
        meta: {
          recordTypeConfig: recordTypeConfig,
          csid: csid
        }
      });
    });
  };
};

var createNewRecord = exports.createNewRecord = function createNewRecord(recordTypeConfig, vocabularyConfig, cloneCsid) {
  return function (dispatch, getState) {
    var readClone = void 0;

    if (cloneCsid) {
      var data = (0, _reducers.getRecordData)(getState(), cloneCsid);

      if (!data) {
        // We don't have data for the record to be cloned. Read it first.

        readClone = dispatch(readRecord(recordTypeConfig, vocabularyConfig, cloneCsid));
      }
    }

    if (!readClone) {
      // There's nothing to clone, or we already have the record data to be cloned. Perform an
      // async noop, so this function will be consistently async.

      readClone = new Promise(function (resolve) {
        window.setTimeout(function () {
          resolve();
        }, 0);
      });
    }

    return readClone.then(function () {
      return dispatch({
        type: CREATE_NEW_RECORD,
        meta: {
          recordTypeConfig: recordTypeConfig,
          cloneCsid: cloneCsid
        }
      });
    });
  };
};

var saveRecord = exports.saveRecord = function saveRecord(recordTypeConfig, vocabularyConfig, csid, relatedSubjectCsid, onRecordCreated) {
  return function (dispatch, getState) {
    dispatch({
      type: RECORD_SAVE_STARTED,
      meta: {
        recordTypeConfig: recordTypeConfig,
        csid: csid,
        relatedSubjectCsid: relatedSubjectCsid
      }
    });

    var data = (0, _reducers.getRecordData)(getState(), csid);

    // TODO: Compute

    return dispatch(validateRecordData(recordTypeConfig, csid)).then(function () {
      if ((0, _reducers.getRecordValidationErrors)(getState(), csid)) {
        dispatch({
          type: RECORD_SAVE_REJECTED,
          payload: {
            code: _errorCodes.ERR_VALIDATION
          },
          meta: {
            recordTypeConfig: recordTypeConfig,
            csid: csid,
            relatedSubjectCsid: relatedSubjectCsid
          }
        });

        return null;
      }

      var title = recordTypeConfig.title((0, _recordDataHelpers.getDocument)(data));
      var notificationID = (0, _notificationHelpers2.default)();

      dispatch((0, _notification.showNotification)({
        message: saveMessages.saving,
        values: {
          title: title,
          hasTitle: title ? 'yes' : ''
        },
        date: new Date(),
        status: _notificationStatusCodes.STATUS_PENDING
      }, notificationID));

      var recordServicePath = recordTypeConfig.serviceConfig.servicePath;

      var vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null;

      var pathParts = [recordServicePath];

      if (vocabularyServicePath) {
        pathParts.push(vocabularyServicePath);
        pathParts.push('items');
      }

      if (csid) {
        pathParts.push(csid);
      }

      var path = pathParts.join('/');

      var config = {
        data: (0, _recordDataHelpers.prepareForSending)(data).toJS()
      };

      if (csid) {
        return (0, _cspace2.default)().update(path, config).then(function (response) {
          dispatch((0, _notification.showNotification)({
            message: saveMessages.saved,
            values: {
              title: title,
              hasTitle: title ? 'yes' : ''
            },
            date: new Date(),
            status: _notificationStatusCodes.STATUS_SUCCESS,
            autoClose: true
          }, notificationID));

          dispatch({
            type: RECORD_SAVE_FULFILLED,
            payload: response,
            meta: {
              recordTypeConfig: recordTypeConfig,
              csid: csid,
              relatedSubjectCsid: relatedSubjectCsid
            }
          });
        }).catch(function (error) {
          dispatch((0, _notification.showNotification)({
            message: saveMessages.errorSaving,
            values: {
              title: title,
              hasTitle: title ? 'yes' : '',
              error: (0, _getErrorDescription2.default)(error)
            },
            date: new Date(),
            status: _notificationStatusCodes.STATUS_ERROR
          }, notificationID));

          dispatch({
            type: RECORD_SAVE_REJECTED,
            payload: {
              code: _errorCodes.ERR_API,
              error: error
            },
            meta: {
              recordTypeConfig: recordTypeConfig,
              csid: csid,
              relatedSubjectCsid: relatedSubjectCsid
            }
          });
        });
      }

      return (0, _cspace2.default)().create(path, config).then(function (response) {
        if (response.status === 201 && response.headers.location) {
          var location = response.headers.location;
          var newRecordCsid = location.substring(location.lastIndexOf('/') + 1);

          return doRead(recordTypeConfig, vocabularyConfig, newRecordCsid).then(function (readResponse) {
            dispatch((0, _notification.showNotification)({
              message: saveMessages.saved,
              values: {
                title: title,
                hasTitle: title ? 'yes' : ''
              },
              date: new Date(),
              status: _notificationStatusCodes.STATUS_SUCCESS,
              autoClose: true
            }, notificationID));

            dispatch({
              type: RECORD_SAVE_FULFILLED,
              payload: readResponse,
              meta: {
                recordTypeConfig: recordTypeConfig,
                csid: newRecordCsid,
                relatedSubjectCsid: relatedSubjectCsid
              }
            });

            if (onRecordCreated) {
              onRecordCreated(newRecordCsid);
            }
          });
        }

        var error = new Error('Expected response with status 201 and a location header');
        error.response = response;

        throw error;
      }).catch(function (error) {
        dispatch((0, _notification.showNotification)({
          message: saveMessages.errorSaving,
          values: {
            title: title,
            hasTitle: title ? 'yes' : '',
            error: (0, _getErrorDescription2.default)(error)
          },
          date: new Date(),
          status: _notificationStatusCodes.STATUS_ERROR
        }, notificationID));

        dispatch({
          type: RECORD_SAVE_REJECTED,
          payload: {
            code: _errorCodes.ERR_API,
            error: error
          },
          meta: {
            recordTypeConfig: recordTypeConfig,
            csid: csid,
            relatedSubjectCsid: relatedSubjectCsid
          }
        });
      });
    });
  };
};

var addFieldInstance = exports.addFieldInstance = function addFieldInstance(recordTypeConfig, csid, path) {
  return function (dispatch) {
    dispatch({
      type: ADD_FIELD_INSTANCE,
      meta: {
        csid: csid,
        path: path,
        recordTypeConfig: recordTypeConfig
      }
    });

    dispatch(validateRecordData(recordTypeConfig, csid));
  };
};

var deleteFieldValue = exports.deleteFieldValue = function deleteFieldValue(recordTypeConfig, csid, path) {
  return function (dispatch) {
    dispatch({
      type: DELETE_FIELD_VALUE,
      meta: {
        csid: csid,
        path: path
      }
    });

    dispatch(validateRecordData(recordTypeConfig, csid));
  };
};

var moveFieldValue = exports.moveFieldValue = function moveFieldValue(recordTypeConfig, csid, path, newPosition) {
  return function (dispatch) {
    dispatch({
      type: MOVE_FIELD_VALUE,
      meta: {
        csid: csid,
        path: path,
        newPosition: newPosition
      }
    });

    dispatch(validateRecordData(recordTypeConfig, csid));
  };
};

var setFieldValue = exports.setFieldValue = function setFieldValue(recordTypeConfig, csid, path, value) {
  return function (dispatch) {
    dispatch({
      type: SET_FIELD_VALUE,
      payload: value,
      meta: {
        csid: csid,
        path: path
      }
    });

    dispatch(validateRecordData(recordTypeConfig, csid));
  };
};

var revertRecord = exports.revertRecord = function revertRecord(recordTypeConfig, csid) {
  return function (dispatch) {
    dispatch({
      type: REVERT_RECORD,
      meta: {
        csid: csid
      }
    });

    // Clear validation errors. Could maybe revalidate here, but to be consistent, we should also
    // validate when a record is first loaded.

    dispatch({
      type: VALIDATION_PASSED,
      meta: {
        csid: csid,
        path: []
      }
    });

    dispatch((0, _notification.removeValidationNotification)());
  };
};

var transitionRecord = exports.transitionRecord = function transitionRecord(recordTypeConfig, vocabularyConfig, csid, transitionName) {
  return function (dispatch, getState) {
    var data = (0, _reducers.getRecordData)(getState(), csid);
    var title = recordTypeConfig.title((0, _recordDataHelpers.getDocument)(data));
    var notificationID = (0, _notificationHelpers2.default)();

    var messages = transitionMessages[transitionName];

    if (messages) {
      dispatch((0, _notification.showNotification)({
        message: messages.transitioning,
        values: {
          title: title,
          hasTitle: title ? 'yes' : ''
        },
        date: new Date(),
        status: _notificationStatusCodes.STATUS_PENDING
      }, notificationID));
    }

    dispatch({
      type: RECORD_TRANSITION_STARTED,
      meta: {
        recordTypeConfig: recordTypeConfig,
        csid: csid,
        transitionName: transitionName
      }
    });

    var recordServicePath = recordTypeConfig.serviceConfig.servicePath;

    var vocabularyServicePath = vocabularyConfig ? vocabularyConfig.serviceConfig.servicePath : null;

    var pathParts = [recordServicePath];

    if (vocabularyServicePath) {
      pathParts.push(vocabularyServicePath);
      pathParts.push('items');
    }

    if (csid) {
      pathParts.push(csid);
    }

    pathParts.push('workflow');
    pathParts.push(transitionName);

    var path = pathParts.join('/');

    return (0, _cspace2.default)().update(path).then(function (response) {
      if (messages) {
        dispatch((0, _notification.showNotification)({
          message: messages.transitioned,
          values: {
            transitionName: transitionName,
            title: title,
            hasTitle: title ? 'yes' : ''
          },
          date: new Date(),
          status: _notificationStatusCodes.STATUS_SUCCESS,
          autoClose: true
        }, notificationID));
      }

      return dispatch({
        type: RECORD_TRANSITION_FULFILLED,
        payload: response,
        meta: {
          recordTypeConfig: recordTypeConfig,
          csid: csid,
          transitionName: transitionName
        }
      });
    }).catch(function (error) {
      if (messages) {
        dispatch((0, _notification.showNotification)({
          message: messages.errorTransitioning,
          values: {
            transitionName: transitionName,
            title: title,
            hasTitle: title ? 'yes' : '',
            error: (0, _getErrorDescription2.default)(error)
          },
          date: new Date(),
          status: _notificationStatusCodes.STATUS_ERROR
        }, notificationID));
      }

      return dispatch({
        type: RECORD_TRANSITION_REJECTED,
        payload: {
          code: _errorCodes.ERR_API,
          error: error
        },
        meta: {
          recordTypeConfig: recordTypeConfig,
          csid: csid,
          transitionName: transitionName
        }
      });
    });
  };
};