'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.isCloneable = exports.getDefaults = exports.getDefaultValue = exports.getVocabularyConfigByShortID = exports.getRecordTypeConfigByServicePath = exports.getRecordTypeConfigByServiceObjectName = exports.normalizeConfig = exports.initConfig = exports.mergeConfig = exports.applyPlugins = exports.applyPlugin = exports.evaluatePlugin = exports.dataPathToFieldDescriptorPath = exports.configKey = undefined;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _immutable = require('immutable');

var _immutable2 = _interopRequireDefault(_immutable);

var _deepAssign = require('deep-assign');

var _deepAssign2 = _interopRequireDefault(_deepAssign);

var _warning = require('warning');

var _warning2 = _interopRequireDefault(_warning);

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

var onlyDigitsPattern = /^\d+$/;
var isNotNumeric = function isNotNumeric(string) {
  return !onlyDigitsPattern.test(string);
};

var configKey = exports.configKey = Symbol.for('configHelpers.configKey');

var dataPathToFieldDescriptorPath = exports.dataPathToFieldDescriptorPath = function dataPathToFieldDescriptorPath(dataPath) {
  return dataPath.filter(isNotNumeric);
};

var evaluatePlugin = exports.evaluatePlugin = function evaluatePlugin(plugin, pluginContext) {
  var pluginType = typeof plugin === 'undefined' ? 'undefined' : _typeof(plugin);

  var isValidType = plugin && (pluginType === 'function' || pluginType === 'object' && !Array.isArray(plugin));

  process.env.NODE_ENV !== 'production' ? (0, _warning2.default)(isValidType, 'A plugin must be an object or a function.') : void 0;

  if (!isValidType) {
    return {};
  }

  return pluginType === 'object' ? plugin : plugin(pluginContext);
};

var applyPlugin = exports.applyPlugin = function applyPlugin(targetConfig, plugin, pluginContext) {
  var pluginConfigContribution = evaluatePlugin(plugin, pluginContext);

  /* eslint-disable no-use-before-define */ // Gotta do this mutual recursion
  return mergeConfig(targetConfig, pluginConfigContribution, pluginContext);
  /* eslint-enable no-use-before-define */
};

var applyPlugins = exports.applyPlugins = function applyPlugins(targetConfig, plugins, pluginContext) {
  var isArray = Array.isArray(plugins);

  process.env.NODE_ENV !== 'production' ? (0, _warning2.default)(isArray, 'Plugins must be an array.') : void 0;

  if (!isArray) {
    return targetConfig;
  }

  return plugins.reduce(function (updatedConfig, plugin) {
    return applyPlugin(updatedConfig, plugin, pluginContext);
  }, targetConfig);
};

var mergeConfig = exports.mergeConfig = function mergeConfig(targetConfig, sourceConfig, pluginContext) {
  var pluginsAppliedConfig = sourceConfig && 'plugins' in sourceConfig ? applyPlugins(targetConfig, sourceConfig.plugins, pluginContext) : targetConfig;

  var mergedConfig = (0, _deepAssign2.default)({}, pluginsAppliedConfig, sourceConfig);

  delete mergedConfig.plugins;

  return mergedConfig;
};

var initConfig = exports.initConfig = function initConfig(config, pluginContext) {
  return mergeConfig({}, config, pluginContext);
};

/*
 * Normalize a configuration object. This function mutates the argument configuration.
 * - Set the name property of each recordTypes entry to its key
 * - Set the name property of each vocabularies entry to its key
 */
var normalizeConfig = exports.normalizeConfig = function normalizeConfig(config) {
  var recordTypes = config.recordTypes;

  Object.keys(recordTypes).forEach(function (recordTypeName) {
    var recordType = recordTypes[recordTypeName];
    var vocabularies = recordType.vocabularies;

    recordType.name = recordTypeName;

    if (vocabularies) {
      Object.keys(vocabularies).forEach(function (vocabularyName) {
        vocabularies[vocabularyName].name = vocabularyName;
      });
    }
  });

  return config;
};

var getRecordTypeConfigByServiceObjectName = exports.getRecordTypeConfigByServiceObjectName = function getRecordTypeConfigByServiceObjectName(config, objectName) {
  if (!config.recordTypesByServiceObjectName) {
    var recordTypesByServiceObjectName = {};
    var recordTypes = config.recordTypes;


    Object.keys(recordTypes).forEach(function (recordType) {
      var recordTypeConfig = recordTypes[recordType];

      recordTypesByServiceObjectName[recordTypeConfig.serviceConfig.objectName] = recordTypeConfig;
    });

    /* eslint-disable no-param-reassign */
    config.recordTypesByServiceObjectName = recordTypesByServiceObjectName;
    /* eslint-enable no-param-reassign */
  }

  return config.recordTypesByServiceObjectName[objectName];
};

var getRecordTypeConfigByServicePath = exports.getRecordTypeConfigByServicePath = function getRecordTypeConfigByServicePath(config, servicePath) {
  if (!config.recordTypesByServicePath) {
    var recordTypesByServicePath = {};
    var recordTypes = config.recordTypes;


    Object.keys(recordTypes).forEach(function (recordType) {
      var recordTypeConfig = recordTypes[recordType];

      recordTypesByServicePath[recordTypeConfig.serviceConfig.servicePath] = recordTypeConfig;
    });

    /* eslint-disable no-param-reassign */
    config.recordTypesByServicePath = recordTypesByServicePath;
    /* eslint-enable no-param-reassign */
  }

  return config.recordTypesByServicePath[servicePath];
};

var getVocabularyConfigByShortID = exports.getVocabularyConfigByShortID = function getVocabularyConfigByShortID(recordTypeConfig, shortID) {
  if (!recordTypeConfig.vocabulariesByShortID) {
    var vocabulariesByShortID = {};
    var vocabularies = recordTypeConfig.vocabularies;


    if (vocabularies) {
      Object.keys(vocabularies).forEach(function (vocabulary) {
        var vocabularyConfig = vocabularies[vocabulary];
        var servicePath = vocabularyConfig.serviceConfig.servicePath;


        if (servicePath && servicePath.indexOf('urn:cspace:name(') === 0 && servicePath.lastIndexOf(')') === servicePath.length - 1) {
          var vocabularyShortID = servicePath.substring(16, servicePath.length - 1);

          vocabulariesByShortID[vocabularyShortID] = vocabularyConfig;
        }
      });

      /* eslint-disable no-param-reassign */
      recordTypeConfig.vocabulariesByShortID = vocabulariesByShortID;
      /* eslint-enable no-param-reassign */
    }
  }

  return recordTypeConfig.vocabulariesByShortID[shortID];
};

var getDefaultValue = exports.getDefaultValue = function getDefaultValue(fieldDescriptor) {
  var config = fieldDescriptor[configKey];

  if (config) {
    var defaultValue = config.defaultValue;


    if ((typeof defaultValue === 'undefined' ? 'undefined' : _typeof(defaultValue)) === 'object' && !_immutable2.default.Map.isMap(defaultValue)) {
      // If an object is supplied as a default value, convert it to an immutable map.

      return _immutable2.default.fromJS(defaultValue);
    }

    return defaultValue;
  }

  return undefined;
};

var getDefaults = exports.getDefaults = function getDefaults(fieldDescriptor) {
  var currentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

  var results = [];

  var defaultValue = getDefaultValue(fieldDescriptor);

  if (typeof defaultValue !== 'undefined') {
    results = results.concat({
      path: currentPath,
      value: defaultValue
    });
  }

  var childKeys = Object.keys(fieldDescriptor).filter(function (key) {
    return key !== configKey;
  });

  childKeys.forEach(function (childKey) {
    var childPath = currentPath.concat(childKey);
    var childfieldDescriptor = fieldDescriptor[childKey];
    var childResults = getDefaults(childfieldDescriptor, childPath);

    results = results.concat(childResults);
  });

  return results;
};

var isCloneable = exports.isCloneable = function isCloneable(fieldDescriptor) {
  var config = fieldDescriptor[configKey];

  if (config && 'cloneable' in config) {
    return config.cloneable;
  }

  return true;
};