const EMPTY_STRING = '';

const GLOBAL = globalThis;
const math = Math;
const mathFloor = math.floor;

const arrayMap = (array, cb) => array.map(cb);
const arrayReduce = (array, cb, initial) => array.reduce(cb, initial);

const mapNew = (entries) => new Map(entries);

const MASK6 = 63;
const ENCODE =
  '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'.split(
    EMPTY_STRING,
  );
mapNew(arrayMap(ENCODE, (char, index) => [char, index]));
const encode = (num) => ENCODE[num & MASK6];

const getRandomValues = GLOBAL.crypto
  ? (array) => GLOBAL.crypto.getRandomValues(array)
  : /* istanbul ignore next */
    (array) => arrayMap(array, () => mathFloor(math.random() * 256));
const defaultSorter = (sortKey1, sortKey2) =>
  (sortKey1 != null ? sortKey1 : 0) < (sortKey2 != null ? sortKey2 : 0)
    ? -1
    : 1;
const getUniqueId = (length = 16) =>
  arrayReduce(
    getRandomValues(new Uint8Array(length)),
    (uniqueId, number) => uniqueId + encode(number),
    '',
  );

export {defaultSorter, getUniqueId};
