import { isPrivateUrl } from "./url-utils.js";
import { getConfig } from "../config.js";
class RateLimiter {
  domains = /* @__PURE__ */ new Map();
  robotsDelays = /* @__PURE__ */ new Map();
  setRobotsCrawlDelay(domain, delaySeconds) {
    this.robotsDelays.set(domain, delaySeconds * 1e3);
  }
  async acquire(url) {
    const domain = new URL(url).hostname;
    const state = this.getOrCreateState(url, domain);
    if (state.activeCount < state.maxConcurrency) {
      const elapsed = Date.now() - state.lastRequestTime;
      const remaining = state.delayMs - elapsed;
      if (remaining > 0 && state.lastRequestTime > 0) {
        await new Promise((r) => setTimeout(r, remaining));
      }
      return this.startRequest(state);
    }
    return new Promise((resolve) => {
      state.queue.push(() => resolve(this.startRequest(state)));
    });
  }
  getOrCreateState(url, domain) {
    if (!this.domains.has(domain)) {
      const config = getConfig();
      const isPrivate = isPrivateUrl(url);
      const configDelay = isPrivate ? config.crawlPrivateDelayMs : config.crawlDelayMs;
      const robotsDelay2 = this.robotsDelays.get(domain) ?? 0;
      const effectiveDelay = Math.max(configDelay, robotsDelay2);
      this.domains.set(domain, {
        activeCount: 0,
        lastRequestTime: 0,
        queue: [],
        maxConcurrency: isPrivate ? config.crawlPrivateConcurrency : config.crawlConcurrency,
        delayMs: effectiveDelay
      });
    }
    const state = this.domains.get(domain);
    const robotsDelay = this.robotsDelays.get(domain);
    if (robotsDelay !== void 0 && robotsDelay > state.delayMs) {
      state.delayMs = robotsDelay;
    }
    return state;
  }
  startRequest(state) {
    state.activeCount++;
    state.lastRequestTime = Date.now();
    return () => {
      state.activeCount--;
      this.processQueue(state);
    };
  }
  processQueue(state) {
    if (state.queue.length === 0 || state.activeCount >= state.maxConcurrency) return;
    const next = state.queue.shift();
    const elapsed = Date.now() - state.lastRequestTime;
    const remaining = state.delayMs - elapsed;
    if (remaining <= 0) {
      next();
    } else {
      setTimeout(next, remaining);
    }
  }
}
export {
  RateLimiter
};
//# sourceMappingURL=rate-limiter.js.map