'use strict';

var $TypeError = require('es-errors/type');
var inspect = require('object-inspect');
var getSideChannelList = require('side-channel-list');
var getSideChannelMap = require('side-channel-map');
var getSideChannelWeakMap = require('side-channel-weakmap');

var makeChannel =
  getSideChannelWeakMap || getSideChannelMap || getSideChannelList;

/** @type {import('.')} */
module.exports = function getSideChannel() {
  /** @typedef {ReturnType<typeof getSideChannel>} Channel */

  /** @type {Channel | undefined} */ var $channelData;

  /** @type {Channel} */
  var channel = {
    assert: function (key) {
      if (!channel.has(key)) {
        throw new $TypeError('Side channel does not contain ' + inspect(key));
      }
    },
    delete: function (key) {
      return !!$channelData && $channelData['delete'](key);
    },
    get: function (key) {
      return $channelData && $channelData.get(key);
    },
    has: function (key) {
      return !!$channelData && $channelData.has(key);
    },
    set: function (key, value) {
      if (!$channelData) {
        $channelData = makeChannel();
      }

      $channelData.set(key, value);
    },
  };
  // @ts-expect-error TODO: figure out why this is erroring
  return channel;
};