"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.get = get;
exports.pathFor = pathFor;
exports.isEqual = isEqual;
exports.numEqualSegments = numEqualSegments;
exports.isSegmentEqual = isSegmentEqual;
exports.hasFocus = hasFocus;
exports.hasItemFocus = hasItemFocus;
exports.isExpanded = isExpanded;
exports.startsWith = startsWith;
exports.trimLeft = trimLeft;
exports.trimRight = trimRight;
exports.trimChildPath = trimChildPath;
exports.toString = toString;
exports.fromString = fromString;
Object.defineProperty(exports, "randomKey", {
  enumerable: true,
  get: function get() {
    return _contentUtils.randomKey;
  }
});
exports.FOCUS_TERMINATOR = void 0;

var _types = require("@sanity/types");

var _contentUtils = require("./contentUtils");

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(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; }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
var reKeySegment = /_key\s*==\s*['"](.*)['"]/;
var EMPTY_PATH = [];
var FOCUS_TERMINATOR = '$';
exports.FOCUS_TERMINATOR = FOCUS_TERMINATOR;

function get(obj, path, defaultVal) {
  var select = typeof path === 'string' ? fromString(path) : path;

  if (!Array.isArray(select)) {
    throw new Error('Path must be an array or a string');
  }

  var acc = obj;

  var _loop = function _loop(i) {
    var segment = select[i];

    if ((0, _types.isIndexSegment)(segment)) {
      if (!Array.isArray(acc)) {
        return {
          v: defaultVal
        };
      }

      acc = acc[segment];
    }

    if ((0, _types.isKeySegment)(segment)) {
      if (!Array.isArray(acc)) {
        return {
          v: defaultVal
        };
      }

      acc = acc.find(item => item._key === segment._key);
    }

    if (typeof segment === 'string') {
      acc = typeof acc === 'object' && acc !== null ? acc[segment] : undefined;
    }

    if (typeof acc === 'undefined') {
      return {
        v: defaultVal
      };
    }
  };

  for (var i = 0; i < select.length; i++) {
    var _ret = _loop(i);

    if (typeof _ret === "object") return _ret.v;
  }

  return acc;
}

var pathsMemo = new Map();

function pathFor(path) {
  if (path.length === 0) {
    return EMPTY_PATH;
  }

  var asString = toString(path);

  if (pathsMemo.has(asString)) {
    return pathsMemo.get(asString);
  }

  pathsMemo.set(asString, path);
  return path;
}

function isEqual(path, otherPath) {
  return path.length === otherPath.length && path.every((segment, i) => isSegmentEqual(segment, otherPath[i]));
}

function numEqualSegments(path, otherPath) {
  var length = Math.min(path.length, otherPath.length);

  for (var i = 0; i < length; i++) {
    if (!isSegmentEqual(path[i], otherPath[i])) {
      return i;
    }
  }

  return length;
}

function isSegmentEqual(segmentA, segmentB) {
  if ((0, _types.isKeySegment)(segmentA) && (0, _types.isKeySegment)(segmentB)) {
    return segmentA._key === segmentB._key;
  }

  if ((0, _types.isIndexSegment)(segmentA)) {
    return Number(segmentA) === Number(segmentB);
  }

  if ((0, _types.isIndexTuple)(segmentA) && (0, _types.isIndexTuple)(segmentB)) {
    return segmentA[0] === segmentB[0] && segmentA[1] === segmentB[1];
  }

  return segmentA === segmentB;
}

function hasFocus(focusPath, path) {
  var withoutTerminator = focusPath[focusPath.length - 1] === FOCUS_TERMINATOR ? focusPath.slice(0, -1) : focusPath;
  return isEqual(withoutTerminator, path);
}

function hasItemFocus(focusPath, item) {
  return focusPath.length === 1 && isSegmentEqual(focusPath[0], item);
}

function isExpanded(segment, focusPath) {
  var _focusPath = _toArray(focusPath),
      head = _focusPath[0],
      tail = _focusPath.slice(1);

  return tail.length > 0 && isSegmentEqual(segment, head);
}

function startsWith(prefix, path) {
  return prefix.every((segment, i) => isSegmentEqual(segment, path[i]));
}

function trimLeft(prefix, path) {
  if (prefix.length === 0 || path.length === 0) {
    return path;
  }

  var _prefix = _toArray(prefix),
      prefixHead = _prefix[0],
      prefixTail = _prefix.slice(1);

  var _path = _toArray(path),
      pathHead = _path[0],
      pathTail = _path.slice(1);

  if (!isSegmentEqual(prefixHead, pathHead)) {
    return path;
  }

  return pathFor(trimLeft(prefixTail, pathTail));
}

function trimRight(suffix, path) {
  var sufLen = suffix.length;
  var pathLen = path.length;

  if (sufLen === 0 || pathLen === 0) {
    return path;
  }

  var i = 0;

  while (i < sufLen && i < pathLen && isSegmentEqual(path[pathLen - i - 1], suffix[sufLen - i - 1])) {
    i++;
  }

  return pathFor(path.slice(0, pathLen - i));
}

function trimChildPath(path, childPath) {
  return startsWith(path, childPath) ? trimLeft(path, childPath) : EMPTY_PATH;
}

function toString(path) {
  if (!Array.isArray(path)) {
    throw new Error('Path is not an array');
  }

  return path.reduce((target, segment, i) => {
    var segmentType = typeof segment;

    if (segmentType === 'number') {
      return "".concat(target, "[").concat(segment, "]");
    }

    if (segmentType === 'string') {
      var separator = i === 0 ? '' : '.';
      return "".concat(target).concat(separator).concat(segment);
    }

    if ((0, _types.isKeySegment)(segment) && segment._key) {
      return "".concat(target, "[_key==\"").concat(segment._key, "\"]");
    }

    if (Array.isArray(segment)) {
      var _segment = _slicedToArray(segment, 2),
          from = _segment[0],
          to = _segment[1];

      return "".concat(target, "[").concat(from, ":").concat(to, "]");
    }

    throw new Error("Unsupported path segment `".concat(JSON.stringify(segment), "`"));
  }, '');
}

function fromString(path) {
  if (typeof path !== 'string') {
    throw new Error('Path is not a string');
  }

  var segments = path.match(rePropName);

  if (!segments) {
    throw new Error('Invalid path string');
  }

  return segments.map(normalizePathSegment);
}

function normalizePathSegment(segment) {
  if ((0, _types.isIndexSegment)(segment)) {
    return normalizeIndexSegment(segment);
  }

  if ((0, _types.isKeySegment)(segment)) {
    return normalizeKeySegment(segment);
  }

  if ((0, _types.isIndexTuple)(segment)) {
    return normalizeIndexTupleSegment(segment);
  }

  return segment;
}

function normalizeIndexSegment(segment) {
  return Number(segment.replace(/[^\d]/g, ''));
}

function normalizeKeySegment(segment) {
  var segments = segment.match(reKeySegment);
  return {
    _key: segments[1]
  };
}

function normalizeIndexTupleSegment(segment) {
  var _segment$split$map = segment.split(':').map(seg => seg === '' ? seg : Number(seg)),
      _segment$split$map2 = _slicedToArray(_segment$split$map, 2),
      from = _segment$split$map2[0],
      to = _segment$split$map2[1];

  return [from, to];
}
/**
 *
 * @deprecated use import {randomKey} from '@sanity/util/content instead
 */