"use strict";

var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard");

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

var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");

require("core-js/modules/es.function.name");

require("core-js/modules/es.object.to-string");

require("core-js/modules/es.regexp.to-string");

_Object$defineProperty(exports, "__esModule", {
  value: true
});

exports.getFields = getFields;
exports.getMedia = getMedia;
exports.getField = getField;

_Object$defineProperty(exports, "createMemoizedStats", {
  enumerable: true,
  get: function get() {
    return _statistics.default;
  }
});

var _getIterator2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/get-iterator"));

var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array"));

var _getIteratorMethod2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/get-iterator-method"));

var _symbol = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/symbol"));

var _from = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/from"));

var _entries = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/entries"));

var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));

var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));

var _values = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/values"));

var _keys = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/keys"));

var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray"));

var _sort = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/sort"));

var _reduce = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/reduce"));

var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify"));

var valueTypes = _interopRequireWildcard(require("../../constants/value_types"));

var _value_types2 = require("./value_types");

var _flat_object_entries = require("../../utils/flat_object_entries");

var _get_set = require("../../utils/get_set");

var _statistics = _interopRequireDefault(require("./statistics"));

function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof _symbol.default === "undefined" || (0, _getIteratorMethod2.default)(o) == null) { if ((0, _isArray.default)(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = (0, _getIterator2.default)(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { var _context5; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = (0, _slice.default)(_context5 = Object.prototype.toString.call(o)).call(_context5, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return (0, _from.default)(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var mediaTypes = [valueTypes.VIDEO_URL, valueTypes.AUDIO_URL, valueTypes.IMAGE_URL];

function compareKeys(a, b) {
  return (0, _stringify.default)(a[0]).localeCompare((0, _stringify.default)(b[0]));
}
/**
 * Takes a JSON object and optional array of JSON objects and returns an array
 * of field definitions. The field definitions are guessed from the arguments
 * passed. The returned field definitions can be used to render fields for
 * editing the properties of the object.
 */


function getFields()
/*: Array<Field>*/
{
  var _context;

  var cur
  /*:: ?: JSONObject*/
  = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  var stats
  /*:: ?: Statistics*/
  = arguments.length > 1 ? arguments[1] : undefined;
  var entries = stats ? flatStatsEntries(stats) : (0, _flat_object_entries.flatObjectEntries)(cur);
  return (0, _reduce.default)(_context = (0, _sort.default)(entries).call(entries, compareKeys)).call(_context, function (acc, _ref) {
    var _ref2 = (0, _slicedToArray2.default)(_ref, 1),
        keyArray = _ref2[0];

    var key = (0, _stringify.default)(keyArray);
    var value = (0, _get_set.get)(cur, keyArray);
    var fieldStats = stats && stats[key];
    var field = getField(keyArray, value, fieldStats);
    if (field) acc.push(field);
    return acc;
  }, []);
}

function getMedia()
/*: MediaArray*/
{
  var _context2;

  var cur
  /*: JSONObject*/
  = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  return (0, _reduce.default)(_context2 = (0, _flat_object_entries.flatObjectEntries)(cur)).call(_context2, function (acc, _ref3) {
    var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
        keyArray = _ref4[0],
        value = _ref4[1];

    var type = (0, _value_types2.guessValueType)(value);

    if ((0, _includes.default)(mediaTypes).call(mediaTypes, type)) {
      // $FlowFixMe flow does not understand type is only media type here
      acc.push({
        src: value,
        type: type
      });
    }

    return acc;
  }, []);
}

function getField(keyArray
/*: Array<string | number>*/
, value
/*: any*/
, fieldStats
/*:: ?: FieldStatistic*/
)
/*: Field*/
{
  var valueType = (0, _value_types2.guessValueType)(value); // Initial implementation does not try to guess from statistics

  switch (valueType) {
    case valueTypes.BOOLEAN:
      return createSelectOneField(keyArray, [true, false]);

    case valueTypes.STRING:
      {
        var options = getOptions(fieldStats);
        if (options.length) return createSelectOneField(keyArray, options);else return createTextField(keyArray);
      }

    case valueTypes.NUMBER:
      return createNumberField(keyArray);

    case valueTypes.ARRAY:
      {
        var _options = getOptions(fieldStats);

        return createSelectMultipleField(keyArray, _options.length ? _options : value, {
          readonly: true
        });
      }

    case valueTypes.DATE:
      return createDateField(keyArray, {
        min: fieldStats && fieldStats.date.min,
        max: fieldStats && fieldStats.date.max
      });

    case valueTypes.DATETIME:
      return createDateTimeField(keyArray, {
        min: fieldStats && fieldStats.date.min,
        max: fieldStats && fieldStats.date.max
      });

    case valueTypes.URL:
    case valueTypes.IMAGE_URL:
    case valueTypes.AUDIO_URL:
    case valueTypes.VIDEO_URL:
      return createLinkField(keyArray);

    default:
      return createTextField(keyArray, {
        readonly: true
      });
  }
} // Don't include long strings in the options that can be selected


var MAX_OPTION_LENGTH = 30;

function getOptions(fieldStats
/*:: ?: FieldStatistic*/
)
/*: SelectOptions*/
{
  var _context3;

  var options = [];
  if (!fieldStats) return options;

  var _iterator = _createForOfIteratorHelper((0, _keys.default)(_context3 = (0, _values.default)(fieldStats.string)).call(_context3)),
      _step;

  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var value = _step.value;
      if (value.length > MAX_OPTION_LENGTH) continue;
      options.push(value);
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }

  return options;
}

function createTextField(keyArray
/*: Array<string | number>*/
)
/*: TextField*/
{
  var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref5$readonly = _ref5.readonly,
      readonly = _ref5$readonly === void 0 ? false : _ref5$readonly,
      _ref5$appearance = _ref5.appearance,
      appearance = _ref5$appearance === void 0 ? 'single' : _ref5$appearance,
      _ref5$snakeCase = _ref5.snakeCase,
      snakeCase = _ref5$snakeCase === void 0 ? false : _ref5$snakeCase;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    appearance: appearance,
    type: 'text'
  };
}

function createLinkField(keyArray
/*: Array<string | number>*/
)
/*: LinkField*/
{
  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: true,
    type: 'link'
  };
}

function createNumberField(keyArray
/*: Array<string | number>*/
)
/*: NumberField*/
{
  var _ref6 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref6$readonly = _ref6.readonly,
      readonly = _ref6$readonly === void 0 ? false : _ref6$readonly;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    type: 'number'
  };
}

function createSelectOneField(keyArray
/*: Array<string | number>*/
, options
/*: SelectOptions*/
)
/*: SelectOneField*/
{
  var _ref7 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
      _ref7$readonly = _ref7.readonly,
      readonly = _ref7$readonly === void 0 ? false : _ref7$readonly,
      _ref7$snakeCase = _ref7.snakeCase,
      snakeCase = _ref7$snakeCase === void 0 ? false : _ref7$snakeCase;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    type: 'select_one',
    options: options
  };
}

function createSelectMultipleField(keyArray
/*: Array<string | number>*/
, options
/*: SelectOptions*/
)
/*: SelectMultipleField*/
{
  var _ref8 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
      _ref8$readonly = _ref8.readonly,
      readonly = _ref8$readonly === void 0 ? false : _ref8$readonly,
      _ref8$snakeCase = _ref8.snakeCase,
      snakeCase = _ref8$snakeCase === void 0 ? false : _ref8$snakeCase;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    type: 'select_multiple',
    options: options
  };
}

function createDateField(keyArray
/*: Array<string | number>*/
)
/*: DateField*/
{
  var _ref9 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref9$readonly = _ref9.readonly,
      readonly = _ref9$readonly === void 0 ? false : _ref9$readonly,
      min = _ref9.min,
      max = _ref9.max;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    type: 'date',
    min_value: min,
    max_value: max
  };
}

function createDateTimeField(keyArray
/*: Array<string | number>*/
)
/*: DateTimeField*/
{
  var _ref10 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref10$readonly = _ref10.readonly,
      readonly = _ref10$readonly === void 0 ? false : _ref10$readonly,
      min = _ref10.min,
      max = _ref10.max;

  return {
    id: (0, _stringify.default)((0, _slice.default)(Array.prototype).call(arguments)),
    key: keyArray,
    readonly: readonly,
    type: 'datetime',
    min_value: min,
    max_value: max
  };
}

function flatStatsEntries(stats
/*: Statistics*/
)
/*: Array<[Array<string | number>, FieldStatistic]>*/
{
  var _context4;

  // $FlowFixMe
  return (0, _map.default)(_context4 = (0, _entries.default)(stats)).call(_context4, function (_ref11) {
    var _ref12 = (0, _slicedToArray2.default)(_ref11, 2),
        key = _ref12[0],
        value = _ref12[1];

    return [JSON.parse(key), value];
  });
}
//# sourceMappingURL=index.js.map