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