"use strict";
/* Socket Lib - Built with esbuild */
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var memoization_exports = {};
__export(memoization_exports, {
  Memoize: () => Memoize,
  clearAllMemoizationCaches: () => clearAllMemoizationCaches,
  memoize: () => memoize,
  memoizeAsync: () => memoizeAsync,
  memoizeDebounced: () => memoizeDebounced,
  memoizeWeak: () => memoizeWeak,
  once: () => once
});
module.exports = __toCommonJS(memoization_exports);
var import_debug = require("./debug");
function memoize(fn, options = {}) {
  const {
    keyGen = (...args) => JSON.stringify(args),
    maxSize = Number.POSITIVE_INFINITY,
    name = fn.name || "anonymous",
    ttl = Number.POSITIVE_INFINITY
  } = options;
  const cache = /* @__PURE__ */ new Map();
  const accessOrder = [];
  function evictLRU() {
    if (cache.size >= maxSize && accessOrder.length > 0) {
      const oldest = accessOrder.shift();
      if (oldest) {
        cache.delete(oldest);
        (0, import_debug.debugLog)(`[memoize:${name}] clear`, {
          key: oldest,
          reason: "LRU"
        });
      }
    }
  }
  function isExpired(entry) {
    if (ttl === Number.POSITIVE_INFINITY) {
      return false;
    }
    return Date.now() - entry.timestamp > ttl;
  }
  return function memoized(...args) {
    const key = keyGen(...args);
    const cached = cache.get(key);
    if (cached && !isExpired(cached)) {
      cached.hits++;
      const index = accessOrder.indexOf(key);
      if (index !== -1) {
        accessOrder.splice(index, 1);
      }
      accessOrder.push(key);
      (0, import_debug.debugLog)(`[memoize:${name}] hit`, { key, hits: cached.hits });
      return cached.value;
    }
    (0, import_debug.debugLog)(`[memoize:${name}] miss`, { key });
    const value = fn(...args);
    evictLRU();
    cache.set(key, {
      value,
      timestamp: Date.now(),
      hits: 0
    });
    accessOrder.push(key);
    (0, import_debug.debugLog)(`[memoize:${name}] set`, { key, cacheSize: cache.size });
    return value;
  };
}
function memoizeAsync(fn, options = {}) {
  const {
    keyGen = (...args) => JSON.stringify(args),
    maxSize = Number.POSITIVE_INFINITY,
    name = fn.name || "anonymous",
    ttl = Number.POSITIVE_INFINITY
  } = options;
  const cache = /* @__PURE__ */ new Map();
  const accessOrder = [];
  function evictLRU() {
    if (cache.size >= maxSize && accessOrder.length > 0) {
      const oldest = accessOrder.shift();
      if (oldest) {
        cache.delete(oldest);
        (0, import_debug.debugLog)(`[memoizeAsync:${name}] clear`, {
          key: oldest,
          reason: "LRU"
        });
      }
    }
  }
  function isExpired(entry) {
    if (ttl === Number.POSITIVE_INFINITY) {
      return false;
    }
    return Date.now() - entry.timestamp > ttl;
  }
  return async function memoized(...args) {
    const key = keyGen(...args);
    const cached = cache.get(key);
    if (cached && !isExpired(cached)) {
      cached.hits++;
      const index = accessOrder.indexOf(key);
      if (index !== -1) {
        accessOrder.splice(index, 1);
      }
      accessOrder.push(key);
      (0, import_debug.debugLog)(`[memoizeAsync:${name}] hit`, { key, hits: cached.hits });
      return await cached.value;
    }
    (0, import_debug.debugLog)(`[memoizeAsync:${name}] miss`, { key });
    const promise = fn(...args);
    evictLRU();
    cache.set(key, {
      value: promise,
      timestamp: Date.now(),
      hits: 0
    });
    accessOrder.push(key);
    (0, import_debug.debugLog)(`[memoizeAsync:${name}] set`, { key, cacheSize: cache.size });
    try {
      const result = await promise;
      return result;
    } catch (e) {
      cache.delete(key);
      const orderIndex = accessOrder.indexOf(key);
      if (orderIndex !== -1) {
        accessOrder.splice(orderIndex, 1);
      }
      (0, import_debug.debugLog)(`[memoizeAsync:${name}] clear`, { key, reason: "error" });
      throw e;
    }
  };
}
function Memoize(options = {}) {
  return (_target, propertyKey, descriptor) => {
    const originalMethod = descriptor.value;
    descriptor.value = memoize(originalMethod, {
      ...options,
      name: options.name || propertyKey
    });
    return descriptor;
  };
}
function clearAllMemoizationCaches() {
  (0, import_debug.debugLog)("[memoize:all] clear", { action: "clear-all-caches" });
}
function memoizeWeak(fn) {
  const cache = /* @__PURE__ */ new WeakMap();
  return function memoized(key) {
    const cached = cache.get(key);
    if (cached !== void 0) {
      (0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] hit`);
      return cached;
    }
    (0, import_debug.debugLog)(`[memoizeWeak:${fn.name}] miss`);
    const result = fn(key);
    cache.set(key, result);
    return result;
  };
}
function once(fn) {
  let called = false;
  let result;
  return function memoized() {
    if (!called) {
      result = fn();
      called = true;
      (0, import_debug.debugLog)(`[once:${fn.name}] set`);
    } else {
      (0, import_debug.debugLog)(`[once:${fn.name}] hit`);
    }
    return result;
  };
}
function memoizeDebounced(fn, wait, options = {}) {
  const memoized = memoize(fn, options);
  let timeoutId;
  return function debounced(...args) {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(() => {
      memoized(...args);
    }, wait);
    return memoized(...args);
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  Memoize,
  clearAllMemoizationCaches,
  memoize,
  memoizeAsync,
  memoizeDebounced,
  memoizeWeak,
  once
});
