import { ExpFilter } from "../../utils.js";
const defaultEndpointingOptions = {
  mode: "fixed",
  minDelay: 500,
  maxDelay: 3e3,
  alpha: 0.9
};
const streamingEndpointingOptions = {
  mode: "fixed",
  minDelay: 300,
  maxDelay: 2500,
  alpha: 0.9
};
const AGENT_SPEECH_LEADING_SILENCE_GRACE_PERIOD = 250;
class BaseEndpointing {
  _minDelay;
  _maxDelay;
  _overlapping = false;
  constructor({ minDelay, maxDelay }) {
    this._minDelay = minDelay;
    this._maxDelay = maxDelay;
  }
  updateOptions({ minDelay, maxDelay }) {
    if (minDelay !== void 0) {
      this._minDelay = minDelay;
    }
    if (maxDelay !== void 0) {
      this._maxDelay = maxDelay;
    }
  }
  get minDelay() {
    return this._minDelay;
  }
  get maxDelay() {
    return this._maxDelay;
  }
  get overlapping() {
    return this._overlapping;
  }
  onStartOfSpeech(_startedAt, overlapping = false) {
    this._overlapping = overlapping;
  }
  onEndOfSpeech(_endedAt, _shouldIgnore = false) {
    this._overlapping = false;
  }
  onStartOfAgentSpeech(_startedAt) {
  }
  onEndOfAgentSpeech(_endedAt) {
  }
}
class DynamicEndpointing extends BaseEndpointing {
  #utterancePause;
  #turnPause;
  #utteranceStartedAt;
  #utteranceEndedAt;
  #agentSpeechStartedAt;
  #agentSpeechEndedAt;
  #speaking = false;
  constructor({
    minDelay,
    maxDelay,
    alpha = 0.9
  }) {
    super({ minDelay, maxDelay });
    this.#utterancePause = new ExpFilter({
      alpha,
      initial: minDelay,
      minVal: minDelay,
      maxVal: maxDelay
    });
    this.#turnPause = new ExpFilter({
      alpha,
      initial: maxDelay,
      minVal: minDelay,
      maxVal: maxDelay
    });
  }
  get minDelay() {
    return this.#utterancePause.value ?? this._minDelay;
  }
  get maxDelay() {
    return Math.max(this.#turnPause.value ?? this._maxDelay, this.minDelay);
  }
  get betweenUtteranceDelay() {
    if (this.#utteranceStartedAt === void 0 || this.#utteranceEndedAt === void 0) {
      return 0;
    }
    return Math.max(0, this.#utteranceStartedAt - this.#utteranceEndedAt);
  }
  get betweenTurnDelay() {
    if (this.#agentSpeechStartedAt === void 0 || this.#utteranceEndedAt === void 0) {
      return 0;
    }
    return Math.max(0, this.#agentSpeechStartedAt - this.#utteranceEndedAt);
  }
  get immediateInterruptionDelay() {
    if (this.#utteranceStartedAt === void 0 || this.#agentSpeechStartedAt === void 0) {
      return [0, 0];
    }
    return [this.betweenTurnDelay, Math.abs(this.betweenUtteranceDelay - this.betweenTurnDelay)];
  }
  onStartOfAgentSpeech(startedAt) {
    this.#agentSpeechStartedAt = startedAt;
    this.#agentSpeechEndedAt = void 0;
    this._overlapping = false;
  }
  onEndOfAgentSpeech(endedAt) {
    if (this.#agentSpeechStartedAt !== void 0 && (this.#agentSpeechEndedAt === void 0 || this.#agentSpeechEndedAt < this.#agentSpeechStartedAt)) {
      this.#agentSpeechEndedAt = endedAt;
    }
    this._overlapping = false;
  }
  onStartOfSpeech(startedAt, overlapping = false) {
    if (this._overlapping) {
      return;
    }
    if (this.#utteranceStartedAt !== void 0 && this.#utteranceEndedAt !== void 0 && this.#agentSpeechStartedAt !== void 0 && this.#utteranceEndedAt < this.#utteranceStartedAt && overlapping) {
      this.#utteranceEndedAt = this.#agentSpeechStartedAt - 1;
    }
    this.#utteranceStartedAt = startedAt;
    this._overlapping = overlapping;
    this.#speaking = true;
  }
  onEndOfSpeech(endedAt, shouldIgnore = false) {
    if (shouldIgnore && this._overlapping) {
      if (this.#utteranceStartedAt === void 0 || this.#agentSpeechStartedAt === void 0 || Math.abs(this.#utteranceStartedAt - this.#agentSpeechStartedAt) >= AGENT_SPEECH_LEADING_SILENCE_GRACE_PERIOD) {
        this._overlapping = false;
        this.#speaking = false;
        this.#utteranceStartedAt = void 0;
        this.#utteranceEndedAt = void 0;
        return;
      }
    }
    const agentStillSpeaking = this.#agentSpeechStartedAt !== void 0 && this.#agentSpeechEndedAt === void 0;
    const betweenUtteranceDelay = this.betweenUtteranceDelay;
    const betweenTurnDelay = this.betweenTurnDelay;
    if (this._overlapping || agentStillSpeaking) {
      const [turnDelay, interruptionDelay] = this.immediateInterruptionDelay;
      const isImmediateInterruption = interruptionDelay > 0 && interruptionDelay <= this.minDelay && turnDelay > 0 && turnDelay <= this.maxDelay && betweenUtteranceDelay > 0;
      if (isImmediateInterruption) {
        this.#utterancePause.apply(1, betweenUtteranceDelay);
      } else if (betweenTurnDelay > 0) {
        this.#turnPause.apply(1, betweenTurnDelay);
      }
    } else if (betweenTurnDelay > 0) {
      this.#turnPause.apply(1, betweenTurnDelay);
    } else {
      const noAgentSpeechAroundPause = this.#agentSpeechEndedAt === void 0 && this.#agentSpeechStartedAt === void 0;
      if (betweenUtteranceDelay > 0 && noAgentSpeechAroundPause) {
        this.#utterancePause.apply(1, betweenUtteranceDelay);
      }
    }
    this.#utteranceEndedAt = endedAt;
    this.#agentSpeechStartedAt = void 0;
    this.#agentSpeechEndedAt = void 0;
    this.#speaking = false;
    this._overlapping = false;
  }
  updateOptions({
    minDelay,
    maxDelay,
    alpha
  }) {
    if (minDelay !== void 0) {
      this._minDelay = minDelay;
      this.#utterancePause.reset({ initial: minDelay, minVal: minDelay });
      this.#turnPause.reset({ minVal: minDelay });
    }
    if (maxDelay !== void 0) {
      this._maxDelay = maxDelay;
      this.#turnPause.reset({ initial: maxDelay, maxVal: maxDelay });
      this.#utterancePause.reset({ maxVal: maxDelay });
    }
    if (alpha !== void 0) {
      this.#utterancePause.reset({ alpha });
      this.#turnPause.reset({ alpha });
    }
  }
}
function createEndpointing(options) {
  if (options.mode === "dynamic") {
    return new DynamicEndpointing({
      minDelay: options.minDelay,
      maxDelay: options.maxDelay,
      alpha: options.alpha
    });
  }
  return new BaseEndpointing({ minDelay: options.minDelay, maxDelay: options.maxDelay });
}
export {
  BaseEndpointing,
  DynamicEndpointing,
  createEndpointing,
  defaultEndpointingOptions,
  streamingEndpointingOptions
};
//# sourceMappingURL=endpointing.js.map