var m = Object.defineProperty;
var d = (n, r, t) => r in n ? m(n, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[r] = t;
var h = (n, r, t) => (d(n, typeof r != "symbol" ? r + "" : r, t), t);
import { UNSAFE_initAccessToken as u } from "../utils/initAccessToken.js";
import { getVirtualRunnerUrl as f } from "../utils/jwt.js";
var w = /* @__PURE__ */ ((n) => (n[n.VISUAL = 0] = "VISUAL", n[n.VOICE = 1] = "VOICE", n[n.COGNITIVE = 2] = "COGNITIVE", n))(w || {});
class k {
  constructor(r) {
    /**
     * Configurations for VirtualService prompting
     */
    h(this, "configs");
    /**
     * 3D Model URL
     */
    h(this, "modelUrl");
    /**
     * Runner URL
     */
    h(this, "runnerUrl");
    /**
     * Runner supported cores
     */
    h(this, "cores");
    this.configs = r, this.modelUrl = "", this.runnerUrl = "", this.cores = [];
  }
  /**
   * Function to initialize modelUrl and runnerUrl.
   */
  async initVirtual() {
    var s;
    let r = localStorage.getItem(`runnerToken${this.configs.virtualId}`) ?? "";
    const t = f(r);
    if (!t)
      throw new Error("Runer URL not found");
    this.runnerUrl = t;
    try {
      const i = await fetch(`${t}/model`, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${r}`
        }
      });
      if (i.status !== 200)
        throw new Error("Fetch model failed");
      const e = await i.json();
      this.modelUrl = ((s = e == null ? void 0 : e.data) == null ? void 0 : s.model) ?? "";
    } catch {
      this.modelUrl = "";
    }
    try {
      const i = await fetch(`${t}/cores`, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${r}`
        }
      });
      if (i.status !== 200)
        throw new Error("Fetch cores failed");
      const e = await i.json();
      this.cores = (e == null ? void 0 : e.data) ?? [], this.initComplete();
    } catch {
      this.cores = [];
    }
  }
  /**
   * Function when init completed
   */
  async initComplete() {
    var t, s;
    const r = [];
    this.modelUrl && r.push(
      0
      /* VISUAL */
    ), this.cores.includes("tts") && r.push(
      1
      /* VOICE */
    ), this.cores.includes("llm") && r.push(
      2
      /* COGNITIVE */
    ), (s = (t = this.configs).onInitCompleted) == null || s.call(t, r);
  }
  /**
   * Function to initialize user session by virtual id
   * @param vid virtualId
   * @param retry function will retry for 3 times, to prevent this behavior, set to a number above 3
   */
  async initSession(r, t = 0) {
    try {
      if (r) {
        const i = await (this.configs.initAccessToken ? this.configs.initAccessToken : u)(r, this.configs.metadata);
        localStorage.setItem(`runnerToken${r}`, i);
      }
      await this.initVirtual();
    } catch (s) {
      if (t >= 3)
        throw s;
      localStorage.removeItem(`runnerToken${r}`), await this.initSession(r, t + 1);
    }
  }
  /**
   * Function to send prompt to the runner service and get Virtual response.
   * @param content text / audio blob contents
   * @param configs additional configuration during prompting
   * @param onPromptReceived callback when prompt is received from the runner service
   * @param retry function will retry for 3 times, to prevent this behavior, set to a number above 3
   * @returns Prompt object
   */
  async createPrompt(r, t, s, i) {
    var e, l;
    try {
      if (!this.configs.virtualId)
        throw new Error("Virtual not found");
      const T = await (this.configs.initAccessToken ? this.configs.initAccessToken : u)(
        this.configs.virtualId ?? -1,
        this.configs.metadata
      ), a = new FormData();
      typeof r != "string" && (a.append("audio", r, "recording.webm"), a.append("skipTTS", t != null && t.skipTTS ? "true" : "false"), a.append("userName", this.configs.userName ?? ""), a.append("botName", this.configs.virtualName ?? ""));
      const c = await fetch(`${this.runnerUrl}/prompts`, {
        method: "POST",
        headers: typeof r == "string" ? {
          "Content-Type": "application/json",
          Authorization: `Bearer ${T}`
        } : {
          Authorization: `Bearer ${T}`
        },
        body: typeof r == "string" ? JSON.stringify({
          text: r,
          skipTTS: t == null ? void 0 : t.skipTTS,
          userName: this.configs.userName,
          botName: this.configs.virtualName
        }) : a
      });
      if (c.status !== 200 && (i ?? 0) < 3)
        return localStorage.removeItem(`runnerToken${this.configs.virtualId}`), await this.initSession(this.configs.virtualId), await this.createPrompt(
          r,
          {
            skipTTS: !!(t != null && t.skipTTS),
            speakOnResponse: !!(t != null && t.speakOnResponse)
          },
          s,
          (i ?? 0) + 1
        );
      if (c.status !== 200)
        throw new Error("Failed to fetch prompt");
      const o = await c.json();
      if (o != null && o.error)
        throw new Error(o.error);
      return s && s(o), o;
    } catch (p) {
      return (i ?? 0) < 3 ? await this.createPrompt(
        r,
        {
          skipTTS: !!(t != null && t.skipTTS),
          speakOnResponse: !!(t != null && t.speakOnResponse)
        },
        s,
        (i ?? 0) + 1
      ) : ((l = (e = this.configs).onPromptError) == null || l.call(e, p), {});
    }
  }
  /**
   * Text-to-speech function
   * @param content text content
   * @returns audio in URL
   */
  async getTTSResponse(r) {
    try {
      if (!this.configs.virtualId)
        throw new Error("Virtual not found");
      const s = await (this.configs.initAccessToken ? this.configs.initAccessToken : u)(
        this.configs.virtualId ?? -1,
        this.configs.metadata
      ), i = await fetch(`${this.runnerUrl}/prompts/voice`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${s}`
        },
        body: JSON.stringify({
          text: r
        })
      }), e = await i.json();
      if (e != null && e.error)
        throw new Error(e.error);
      return i.status !== 200 ? "" : (e == null ? void 0 : e.audioUid) ?? "";
    } catch (t) {
      return this.configs.onPromptError && this.configs.onPromptError(t), "";
    }
  }
}
const y = new k({});
export {
  w as Core,
  k as VirtualService,
  y as defaultVirtualService
};
