'use strict';

require('../utils/types/array.cjs');
var utils_types_iterable = require('../utils/types/iterable.cjs');
require('crypto');
require('bs58');
require('multiformats/bases/base58');
require('varint');
require('../utils/encoding/ss-58.cjs');
require('../utils/inheritance.cjs');
require('../utils/types/object.cjs');
require('../utils/types/set.cjs');
require('blake2b');
require('../utils/types/bytes.cjs');
require('../utils/interfaces.cjs');
require('../utils/assert.cjs');
require('../utils/error.cjs');
require('../utils/types/string.cjs');

/**
 * Caches last function result and returns it if function called with the same args again.
 * @param {Function}
 * @returns {Function}
 */
const cacheLast = (fn) => {
  let lastArgs;
  let lastValue;

  return function cached(...args) {
    if (lastArgs !== void 0) {
      let same = true;
      const length = Math.max(lastArgs.length, args.length);
      for (let i = 0; i < length && same; ++i) {
        same &&= lastArgs[i] === args[i];
      }

      if (same) {
        return lastValue;
      }
    }
    lastValue = fn.apply(this, args);
    lastArgs = args;

    return lastValue;
  };
};

/**
 * Ensures that each item is present in the allowed set and that both sets are valid.
 *
 * @template I
 * @template W
 * @param {Iterable<I | W>} items
 * @param {Iterable<T | W>} allowed
 * @param {W} wildcard
 */
const ensureItemsAllowed = (items, allowed, wildcard) => {
  const itemsSet = new Set(items);
  const allowedSet = new Set(allowed);
  if (items.size === 0) {
    throw new Error('Empty item set provided');
  }
  if (allowed.size === 0) {
    throw new Error('Empty allowed set provided');
  }

  for (const toCheck of [itemsSet, allowedSet]) {
    if (toCheck.has(wildcard) && toCheck.size > 1) {
      throw new Error(
        `Can't have wildcard mixed with other patterns for ${utils_types_iterable.fmtIterable(
          toCheck,
        )}`,
      );
    }
  }

  if (allowedSet.has(wildcard)) return;

  for (const item of itemsSet) {
    if (!allowedSet.has(item)) {
      throw new Error(
        `Item not found in ${utils_types_iterable.fmtIterable(allowedSet)}: \`${item.toString()}\``,
      );
    }
  }
};

const itemsOrWildcard = (items, wildcard) => {
  for (const item of items) {
    if (item === wildcard) {
      return wildcard;
    }
  }

  return [...new Set(items)];
};

exports.cacheLast = cacheLast;
exports.ensureItemsAllowed = ensureItemsAllowed;
exports.itemsOrWildcard = itemsOrWildcard;
//# sourceMappingURL=utils.cjs.map
