import { a as o } from "../../../../three-vrm.module-BuztCP2r.js";
import { r as R, F as B, S as I, V as y, Q as A, s as C, c as V, b as v, A as U } from "../../../../three.module-BPupfU8l.js";
import { transverse as F, centerOfDescendant as w } from "../../three-helpers.js";
class q extends R {
  constructor(n) {
    super(n), this.animateBonePositions = !0, this.animateBoneRotations = !0;
  }
  load(n, e, t, l) {
    const h = this, E = new B(h.manager);
    E.setPath(h.path), E.setRequestHeader(h.requestHeader), E.setWithCredentials(h.withCredentials), E.load(n, function(c) {
      try {
        e(h.parse(c));
      } catch (p) {
        l ? l(p) : console.error(p), h.manager.itemError(n);
      }
    }, t, l);
  }
  parse(n) {
    function e(r) {
      c(r) !== "HIERARCHY" && console.error("THREE.BVHLoader: HIERARCHY expected.");
      const u = [], f = l(r, c(r), u);
      c(r) !== "MOTION" && console.error("THREE.BVHLoader: MOTION expected.");
      let s = c(r).split(/[\s]+/);
      const i = parseInt(s[1]);
      isNaN(i) && console.error("THREE.BVHLoader: Failed to read number of frames."), s = c(r).split(/[\s]+/);
      const g = parseFloat(s[2]);
      isNaN(g) && console.error("THREE.BVHLoader: Failed to read frame time.");
      for (let d = 0; d < i; d++)
        s = c(r).split(/[\s]+/), t(s, d * g, f);
      return u;
    }
    function t(r, u, f) {
      if (f.type === "ENDSITE")
        return;
      const s = {
        time: u,
        position: new y(),
        rotation: new A()
      };
      f.frames.push(s);
      const i = new A(), g = new y(1, 0, 0), d = new y(0, 1, 0), N = new y(0, 0, 1);
      for (let m = 0; m < f.channels.length; m++)
        switch (f.channels[m]) {
          case "Xposition":
            s.position.x = parseFloat(r.shift().trim());
            break;
          case "Yposition":
            s.position.y = parseFloat(r.shift().trim());
            break;
          case "Zposition":
            s.position.z = parseFloat(r.shift().trim());
            break;
          case "Xrotation":
            i.setFromAxisAngle(g, parseFloat(r.shift().trim()) * Math.PI / 180), s.rotation.multiply(i);
            break;
          case "Yrotation":
            i.setFromAxisAngle(d, parseFloat(r.shift().trim()) * Math.PI / 180), s.rotation.multiply(i);
            break;
          case "Zrotation":
            i.setFromAxisAngle(N, parseFloat(r.shift().trim()) * Math.PI / 180), s.rotation.multiply(i);
            break;
          default:
            console.warn("THREE.BVHLoader: Invalid channel type.");
        }
      for (let m = 0; m < f.children.length; m++)
        t(r, u, f.children[m]);
    }
    function l(r, u, f) {
      const s = { name: "", type: "", frames: [] };
      f.push(s);
      let i = u.split(/[\s]+/);
      i[0].toUpperCase() === "END" && i[1].toUpperCase() === "SITE" ? (s.type = "ENDSITE", s.name = "ENDSITE") : (s.name = i[1], s.type = i[0].toUpperCase()), c(r) !== "{" && console.error("THREE.BVHLoader: Expected opening { after type & name"), i = c(r).split(/[\s]+/), i[0] !== "OFFSET" && console.error("THREE.BVHLoader: Expected OFFSET but got: " + i[0]), i.length !== 4 && console.error("THREE.BVHLoader: Invalid number of values for OFFSET.");
      const g = new y(
        parseFloat(i[1]),
        parseFloat(i[2]),
        parseFloat(i[3])
      );
      if ((isNaN(g.x) || isNaN(g.y) || isNaN(g.z)) && console.error("THREE.BVHLoader: Invalid values of OFFSET."), s.offset = g, s.type !== "ENDSITE") {
        i = c(r).split(/[\s]+/), i[0] !== "CHANNELS" && console.error("THREE.BVHLoader: Expected CHANNELS definition.");
        const d = parseInt(i[1]);
        s.channels = i.splice(2, d), s.children = [];
      }
      for (; ; ) {
        const d = c(r);
        if (d === "}")
          return s;
        s.children.push(l(r, d, f));
      }
    }
    function h(r, u) {
      const f = new C();
      if (u.push(f), f.position.add(r.offset), f.name = r.name, r.type !== "ENDSITE")
        for (let s = 0; s < r.children.length; s++)
          f.add(h(r.children[s], u));
      return f;
    }
    function E(r) {
      const u = [];
      for (let f = 0; f < r.length; f++) {
        const s = r[f];
        if (s.type === "ENDSITE")
          continue;
        const i = [], g = [], d = [];
        for (let N = 0; N < s.frames.length; N++) {
          const m = s.frames[N];
          i.push(m.time), g.push(m.position.x + s.offset.x), g.push(m.position.y + s.offset.y), g.push(m.position.z + s.offset.z), d.push(m.rotation.x), d.push(m.rotation.y), d.push(m.rotation.z), d.push(m.rotation.w);
        }
        p.animateBonePositions && u.push(new V(s.name + ".position", i, g)), p.animateBoneRotations && u.push(new v(s.name + ".quaternion", i, d));
      }
      return new U("animation", -1, u);
    }
    function c(r) {
      let u;
      for (; (u = r.shift().trim()).length === 0; )
        ;
      return u;
    }
    const p = this, L = n.split(/[\r\n]+/g), k = e(L), T = [];
    h(k[0], T);
    const x = E(k);
    return {
      skeleton: new I(T),
      clip: x
    };
  }
}
const D = /^\.bones\[(.+)\]\.(position|quaternion)$/, M = new A(), O = new y();
function z(a) {
  const n = a.filter((e) => e.parent == null);
  if (n.length !== 1)
    throw new TypeError("Requires unique root.");
  return n[0];
}
function H(a, n) {
  if (!n || !n.length)
    throw new TypeError("No bones.");
  let e = n[0];
  for (let t = 1; t < n.length; t++)
    e = a(e, n[t]);
  return e;
}
function $(a, n) {
  if (a.children.length !== 3)
    throw new TypeError("Hips require 3 children.");
  n.set(
    o.Spine,
    H(
      (e, t) => w(e).y > w(t).y ? e : t,
      a.children
    )
  ), n.set(
    o.LeftUpperLeg,
    H(
      (e, t) => w(e).x < w(t).x ? e : t,
      a.children
    )
  ), n.set(
    o.RightUpperLeg,
    H(
      (e, t) => w(e).x > w(t).x ? e : t,
      a.children
    )
  );
}
function P(a, n) {
  if (a.children.length !== 3)
    throw new TypeError("Chest require 3 children.");
  n.set(
    o.Neck,
    H(
      (e, t) => w(e).y > w(t).y ? e : t,
      a.children
    )
  ), n.set(
    o.LeftShoulder,
    H(
      (e, t) => w(e).x < w(t).x ? e : t,
      a.children
    )
  ), n.set(
    o.RightShoulder,
    H(
      (e, t) => w(e).x > w(t).x ? e : t,
      a.children
    )
  );
}
function S(a, n) {
  const e = Array.from(
    F(
      a.get(
        n ? o.RightShoulder : o.LeftShoulder
      )
    )
  );
  switch (e.length) {
    case 0:
    case 1:
    case 2:
    case 3:
      throw new TypeError(`Not supported (${e.length})`);
    default:
      a.set(
        n ? o.RightShoulder : o.LeftShoulder,
        e[0]
      ), a.set(
        n ? o.RightUpperArm : o.LeftUpperArm,
        e[1]
      ), a.set(
        n ? o.RightLowerArm : o.LeftLowerArm,
        e[2]
      ), a.set(
        n ? o.RightHand : o.LeftHand,
        e[3]
      );
      break;
  }
}
function b(a, n) {
  const e = Array.from(
    F(
      a.get(
        n ? o.RightUpperLeg : o.LeftUpperLeg
      )
    )
  );
  switch (e.length) {
    case 0:
    case 1:
    case 2:
      throw new TypeError(`Not supported (${e.length})`);
    case 3:
      a.set(
        n ? o.RightUpperLeg : o.LeftUpperLeg,
        e[0]
      ), a.set(
        n ? o.RightLowerLeg : o.LeftLowerLeg,
        e[1]
      ), a.set(
        n ? o.RightFoot : o.LeftFoot,
        e[2]
      );
      break;
    default:
      a.set(
        n ? o.RightUpperLeg : o.LeftUpperLeg,
        e[e.length - 4]
      ), a.set(
        n ? o.RightLowerLeg : o.LeftLowerLeg,
        e[e.length - 3]
      ), a.set(
        n ? o.RightFoot : o.LeftFoot,
        e[e.length - 2]
      ), a.set(
        n ? o.RightToes : o.LeftToes,
        e[e.length - 1]
      );
      break;
  }
}
function Q(a) {
  const n = z(a.bones);
  let e;
  for (const c of F(n))
    if (c.children.length === 3) {
      e = c;
      break;
    }
  if (!e)
    throw new TypeError("Hips not found");
  const t = /* @__PURE__ */ new Map();
  $(e, t), b(t, !1), b(t, !0);
  const l = [];
  for (const c of F(t.get(o.Spine)))
    if (l.push(c), c.children.length === 3)
      break;
  P(l[l.length - 1], t), S(t, !1), S(t, !0);
  const h = Array.from(F(t.get(o.Neck)));
  switch (l.length) {
    case 0:
      throw new TypeError(`Not supported (${l.length})`);
    case 1:
      t.set(o.Spine, l[0]);
      break;
    case 2:
      t.set(o.Spine, l[0]), t.set(o.Chest, l[1]);
      break;
    default:
      t.set(o.Spine, l[0]), t.set(o.Chest, l[1]), t.set(
        o.UpperChest,
        l[l.length - 1]
      );
      break;
  }
  switch (h.length) {
    case 0:
      throw new TypeError(`Not supported (${h.length})`);
    case 1:
      t.set(o.Head, l[0]);
      break;
    case 2:
      t.set(o.Neck, l[0]), t.set(o.Head, l[1]);
      break;
    default:
      t.set(o.Neck, l[0]);
      let c;
      for (const p of h)
        p.parent.children.length === 1 && (c = p);
      if (!c)
        throw new TypeError("Head not found");
      t.set(o.Head, c);
      break;
  }
  const E = /* @__PURE__ */ new Map();
  for (const [c, p] of t)
    E.set(p.name, [c, p]);
  return E;
}
function Z(a, n) {
  var c;
  const e = new TextDecoder(), { clip: t, skeleton: l } = new q().parse(e.decode(a)), h = /* @__PURE__ */ new Set(), E = Q(l);
  for (const p of t.tracks) {
    const L = p.name.match(D);
    if (!L || !E.has(L[1]))
      continue;
    const [k, T] = E.get(L[1]);
    if (k !== o.Hips && L[2] !== "quaternion")
      continue;
    const x = (c = n.humanoid) == null ? void 0 : c.getNormalizedBoneNode(k);
    if (x) {
      switch (L[2]) {
        case "quaternion":
          for (let r = 0; r < p.times.length; r++)
            M.fromArray(p.values, r * 4).premultiply(T.quaternion).toArray(p.values, r * 4);
          break;
        case "position":
          for (let r = 0; r < p.times.length; r++)
            O.fromArray(p.values, r * 3).add(T.position).toArray(p.values, r * 3);
          break;
      }
      p.name = `${x.name}.${L[2]}`, h.add(p);
    }
  }
  return h.size !== t.tracks.length && (t.tracks = Array.from(h)), t.resetDuration();
}
export {
  Z as convert
};
