'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _immutable = require('immutable');

var _immutable2 = _interopRequireDefault(_immutable);

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

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

var _get2 = _interopRequireDefault(_get);

var _cspaceInput = require('cspace-input');

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

var _PermissionButton = require('../../../styles/cspace-ui/PermissionButton.css');

var _PermissionButton2 = _interopRequireDefault(_PermissionButton);

var _PermissionsInput = require('../../../styles/cspace-ui/PermissionsInput.css');

var _PermissionsInput2 = _interopRequireDefault(_PermissionsInput);

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

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var _inputHelpers$pathHel = _cspaceInput.helpers.pathHelpers,
    getPath = _inputHelpers$pathHel.getPath,
    pathPropType = _inputHelpers$pathHel.pathPropType;


var permMessages = (0, _reactIntl.defineMessages)({
  '': {
    'id': 'permissionsInput.perm.none',
    'defaultMessage': 'None'
  },
  RL: {
    'id': 'permissionsInput.perm.read',
    'defaultMessage': 'Read'
  },
  CRUL: {
    'id': 'permissionsInput.perm.write',
    'defaultMessage': 'Write'
  },
  CRUDL: {
    'id': 'permissionsInput.perm.delete',
    'defaultMessage': 'Delete'
  }
});

var serviceTypeMessages = (0, _reactIntl.defineMessages)({
  object: {
    'id': 'permissionsInput.serviceType.object',
    'defaultMessage': 'Objects'
  },
  procedure: {
    'id': 'permissionsInput.serviceType.procedure',
    'defaultMessage': 'Procedures'
  },
  authority: {
    'id': 'permissionsInput.serviceType.authority',
    'defaultMessage': 'Authorities'
  },
  utility: {
    'id': 'permissionsInput.serviceType.utility',
    'defaultMessage': 'Utility Resources'
  },
  security: {
    'id': 'permissionsInput.serviceType.security',
    'defaultMessage': 'Security Resources'
  }
});

var serviceTypes = ['object', 'procedure', 'authority', 'utility', 'security'];

var propTypes = {
  /* eslint-disable react/no-unused-prop-types */
  name: _propTypes2.default.string,
  parentPath: pathPropType,
  subpath: pathPropType,
  /* eslint-enable react/no-unused-prop-types */
  readOnly: _propTypes2.default.bool,
  resourceNames: _propTypes2.default.instanceOf(_immutable2.default.List),
  value: _propTypes2.default.oneOfType([_propTypes2.default.instanceOf(_immutable2.default.List), _propTypes2.default.instanceOf(_immutable2.default.Map)]),
  readPerms: _propTypes2.default.func,
  onCommit: _propTypes2.default.func
};

var contextTypes = {
  intl: _reactIntl.intlShape,
  config: _propTypes2.default.object
};

var PermissionsInput = function (_Component) {
  _inherits(PermissionsInput, _Component);

  function PermissionsInput(props, context) {
    _classCallCheck(this, PermissionsInput);

    var _this = _possibleConstructorReturn(this, (PermissionsInput.__proto__ || Object.getPrototypeOf(PermissionsInput)).call(this, props, context));

    _this.handleRadioChange = _this.handleRadioChange.bind(_this);
    return _this;
  }

  _createClass(PermissionsInput, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      var _props = this.props,
          resourceNames = _props.resourceNames,
          readPerms = _props.readPerms;
      var config = this.context.config;


      if (!resourceNames && readPerms) {
        readPerms(config);
      }
    }
  }, {
    key: 'getPermsMap',
    value: function getPermsMap() {
      // The services layer gives us a list of resources and action groups. Build a map of resource
      // names to UI permissions.

      var permissionsList = this.props.value;

      if (!permissionsList) {
        return undefined;
      }

      if (!_immutable2.default.List.isList(permissionsList)) {
        permissionsList = _immutable2.default.List.of(permissionsList);
      }

      var perms = {};

      permissionsList.forEach(function (permission) {
        var resourceName = permission.get('resourceName');
        var actionGroup = permission.get('actionGroup');

        perms[resourceName] = actionGroup;
      });

      return perms;
    }
  }, {
    key: 'updatePerms',
    value: function updatePerms(updates) {
      var perms = this.getPermsMap() || {};

      Object.assign(perms, updates);

      return _immutable2.default.List(Object.keys(perms).filter(function (resourceName) {
        return !!perms[resourceName];
      }).map(function (resourceName) {
        return _immutable2.default.Map({
          resourceName: resourceName,
          actionGroup: perms[resourceName]
        });
      }));
    }
  }, {
    key: 'handleRadioChange',
    value: function handleRadioChange(event) {
      var _event$target = event.target,
          recordType = _event$target.name,
          actionGroup = _event$target.value,
          selected = _event$target.checked;
      var onCommit = this.props.onCommit;


      if (selected && onCommit) {
        var config = this.context.config;


        var serviceConfig = (0, _get2.default)(config, ['recordTypes', recordType, 'serviceConfig']);

        var documentName = serviceConfig.documentName,
            servicePath = serviceConfig.servicePath,
            serviceType = serviceConfig.serviceType;


        var resourceName = servicePath;

        var update = _defineProperty({}, resourceName, actionGroup);

        if (serviceType === 'object' || serviceType === 'procedure' || serviceType === 'authority' || serviceType === 'utility') {
          // For object, procedure, authority, and utility types, also set permissions on the delete
          // workflow transition. (Security records do not have soft-delete).

          var workflowDeleteResourceName = '/' + resourceName + '/*/workflow/delete';

          if (actionGroup) {
            update[workflowDeleteResourceName] = actionGroup.includes('D') ? 'CRUDL' : 'RL';
          } else {
            update[workflowDeleteResourceName] = '';
          }
        }

        if (serviceType === 'authority') {
          // Permissions on authorities should be set on both the authorities and their items.

          var itemResourceName = documentName;

          update[itemResourceName] = actionGroup;
        }

        var updatedPerms = this.updatePerms(update);

        onCommit(getPath(this.props), updatedPerms);
      }
    }
  }, {
    key: 'renderRadioButton',
    value: function renderRadioButton(perms, recordType, resourceName, value) {
      var readOnly = this.props.readOnly;


      var className = readOnly ? _PermissionButton2.default.readOnly : _PermissionButton2.default.normal;

      var checked = false;

      if (perms) {
        checked = value ? perms[resourceName] === value : !perms[resourceName];
      }

      return (
        // FIXME: Do I really need for if I'm wrapping the input in the label?
        // eslint-disable-next-line jsx-a11y/label-has-for
        _react2.default.createElement(
          'label',
          { className: className },
          _react2.default.createElement(_reactIntl.FormattedMessage, permMessages[value]),
          _react2.default.createElement('input', {
            checked: checked,
            name: recordType,
            type: 'radio',
            value: value,
            disabled: readOnly,
            onChange: this.handleRadioChange
          }),
          _react2.default.createElement('div', null)
        )
      );
    }
  }, {
    key: 'renderPermRows',
    value: function renderPermRows() {
      var _this2 = this;

      var _context = this.context,
          config = _context.config,
          intl = _context.intl;
      var resourceNames = this.props.resourceNames;


      var perms = this.getPermsMap();

      var recordTypeConfigs = resourceNames.map(function (resourceName) {
        return (0, _configHelpers.getRecordTypeConfigByServicePath)(config, resourceName);
      }).filter(function (recordTypeConfig) {
        return recordTypeConfig && !recordTypeConfig.disabled;
      });

      var sections = [];

      serviceTypes.forEach(function (serviceType) {
        var rows = [];

        recordTypeConfigs.filter(function (recordTypeConfig) {
          return recordTypeConfig.serviceConfig.serviceType === serviceType;
        }).sort(function (recordTypeConfigA, recordTypeConfigB) {
          // Primary sort by sortOrder

          var sortOrderA = recordTypeConfigA.sortOrder;
          var sortOrderB = recordTypeConfigB.sortOrder;

          if (typeof sortOrderA !== 'number') {
            sortOrderA = Number.MAX_VALUE;
          }

          if (typeof sortOrderB !== 'number') {
            sortOrderB = Number.MAX_VALUE;
          }

          if (sortOrderA !== sortOrderB) {
            return sortOrderA > sortOrderB ? 1 : -1;
          }

          // Secondary sort by label

          var labelA = intl.formatMessage(recordTypeConfigA.messages.record.collectionName);
          var labelB = intl.formatMessage(recordTypeConfigB.messages.record.collectionName);

          // FIXME: This should be locale aware
          return labelA.localeCompare(labelB);
        }).forEach(function (recordTypeConfig) {
          var name = recordTypeConfig.name;
          var resourceName = recordTypeConfig.serviceConfig.servicePath;
          var nameMessage = (0, _get2.default)(recordTypeConfig, ['messages', 'record', 'collectionName']);

          var formattedName = nameMessage ? intl.formatMessage(nameMessage) : '[ ' + name + ' ]';

          rows.push(_react2.default.createElement(
            'div',
            { key: name },
            _react2.default.createElement(
              'div',
              null,
              formattedName
            ),
            _react2.default.createElement(
              'div',
              null,
              _this2.renderRadioButton(perms, name, resourceName, ''),
              _this2.renderRadioButton(perms, name, resourceName, 'RL'),
              _this2.renderRadioButton(perms, name, resourceName, 'CRUL'),
              _this2.renderRadioButton(perms, name, resourceName, 'CRUDL')
            )
          ));
        });

        sections.push(_react2.default.createElement(
          'section',
          { key: serviceType },
          _react2.default.createElement(
            'header',
            null,
            _react2.default.createElement(
              'h3',
              null,
              _react2.default.createElement(_reactIntl.FormattedMessage, serviceTypeMessages[serviceType])
            ),
            _react2.default.createElement(
              'ul',
              null,
              _react2.default.createElement(
                'li',
                null,
                _react2.default.createElement(_reactIntl.FormattedMessage, permMessages[''])
              ),
              _react2.default.createElement(
                'li',
                null,
                _react2.default.createElement(_reactIntl.FormattedMessage, permMessages.RL)
              ),
              _react2.default.createElement(
                'li',
                null,
                _react2.default.createElement(_reactIntl.FormattedMessage, permMessages.CRUL)
              ),
              _react2.default.createElement(
                'li',
                null,
                _react2.default.createElement(_reactIntl.FormattedMessage, permMessages.CRUDL)
              )
            )
          ),
          rows
        ));
      });

      return sections;
    }
  }, {
    key: 'render',
    value: function render() {
      var _props2 = this.props,
          readOnly = _props2.readOnly,
          resourceNames = _props2.resourceNames;


      if (!resourceNames) {
        return null;
      }

      var value = this.props.value;


      if (value && !_immutable2.default.List.isList(value)) {
        value = _immutable2.default.List.of(value);
      }

      var className = readOnly ? _PermissionsInput2.default.readOnly : _PermissionsInput2.default.common;

      return _react2.default.createElement(
        'div',
        { className: className },
        this.renderPermRows()
      );
    }
  }]);

  return PermissionsInput;
}(_react.Component);

exports.default = PermissionsInput;


PermissionsInput.propTypes = propTypes;
PermissionsInput.contextTypes = contextTypes;