import d, { useContext as Q, createContext as te, useRef as C, useState as M, useMemo as ne, Fragment as U, useEffect as ge } from "react";
import { useDisposables as Te } from "../../hooks/use-disposables.js";
import { useEvent as E } from "../../hooks/use-event.js";
import { useIsMounted as Ce } from "../../hooks/use-is-mounted.js";
import { useIsoMorphicEffect as L } from "../../hooks/use-iso-morphic-effect.js";
import { useLatestValue as Ee } from "../../hooks/use-latest-value.js";
import { useServerHandoffComplete as le } from "../../hooks/use-server-handoff-complete.js";
import { useSyncRefs as ie } from "../../hooks/use-sync-refs.js";
import { useTransition as we, transitionDataAttributes as Re } from "../../hooks/use-transition.js";
import { useOpenClosed as se, State as F, OpenClosedProvider as $e } from "../../internal/open-closed.js";
import { classNames as Pe } from "../../utils/class-names.js";
import { match as ae } from "../../utils/match.js";
import { forwardRefWithAs as X, useRender as oe, RenderFeatures as Se, RenderStrategy as S, compact as ye } from "../../utils/render.js";
function ue(e) {
  var r;
  return !!(e.enter || e.enterFrom || e.enterTo || e.leave || e.leaveFrom || e.leaveTo) || ((r = e.as) != null ? r : de) !== U || d.Children.count(e.children) === 1;
}
let j = te(null);
j.displayName = "TransitionContext";
var Fe = ((e) => (e.Visible = "visible", e.Hidden = "hidden", e))(Fe || {});
function He() {
  let e = Q(j);
  if (e === null) throw new Error("A <Transition.Child /> is used but it is missing a parent <Transition /> or <Transition.Root />.");
  return e;
}
function Oe() {
  let e = Q(z);
  if (e === null) throw new Error("A <Transition.Child /> is used but it is missing a parent <Transition /> or <Transition.Root />.");
  return e;
}
let z = te(null);
z.displayName = "NestingContext";
function K(e) {
  return "children" in e ? K(e.children) : e.current.filter(({ el: r }) => r.current !== null).filter(({ state: r }) => r === "visible").length > 0;
}
function ce(e, r) {
  let n = Ee(e), a = C([]), w = Ce(), y = Te(), f = E((i, t = S.Hidden) => {
    let s = a.current.findIndex(({ el: l }) => l === i);
    s !== -1 && (ae(t, { [S.Unmount]() {
      a.current.splice(s, 1);
    }, [S.Hidden]() {
      a.current[s].state = "hidden";
    } }), y.microTask(() => {
      var l;
      !K(a) && w.current && ((l = n.current) == null || l.call(n));
    }));
  }), R = E((i) => {
    let t = a.current.find(({ el: s }) => s === i);
    return t ? t.state !== "visible" && (t.state = "visible") : a.current.push({ el: i, state: "visible" }), () => f(i, S.Unmount);
  }), h = C([]), c = C(Promise.resolve()), m = C({ enter: [], leave: [] }), p = E((i, t, s) => {
    h.current.splice(0), r && (r.chains.current[t] = r.chains.current[t].filter(([l]) => l !== i)), r == null || r.chains.current[t].push([i, new Promise((l) => {
      h.current.push(l);
    })]), r == null || r.chains.current[t].push([i, new Promise((l) => {
      Promise.all(m.current[t].map(([$, H]) => H)).then(() => l());
    })]), t === "enter" ? c.current = c.current.then(() => r == null ? void 0 : r.wait.current).then(() => s(t)) : s(t);
  }), b = E((i, t, s) => {
    Promise.all(m.current[t].splice(0).map(([l, $]) => $)).then(() => {
      var l;
      (l = h.current.shift()) == null || l();
    }).then(() => s(t));
  });
  return ne(() => ({ children: a, register: R, unregister: f, onStart: p, onStop: b, wait: c, chains: m }), [R, f, a, p, b, m, c]);
}
let de = U, fe = Se.RenderStrategy;
function Ae(e, r) {
  var n, a;
  let { transition: w = !0, beforeEnter: y, afterEnter: f, beforeLeave: R, afterLeave: h, enter: c, enterFrom: m, enterTo: p, entered: b, leave: i, leaveFrom: t, leaveTo: s, ...l } = e, [$, H] = M(null), o = C(null), g = ue(e), P = ie(...g ? [o, r, H] : r === null ? [] : [r]), Y = (n = l.unmount) == null || n ? S.Unmount : S.Hidden, { show: v, appear: Z, initial: _ } = He(), [T, V] = M(v ? "visible" : "hidden"), q = Oe(), { register: x, unregister: N } = q;
  L(() => x(o), [x, o]), L(() => {
    if (Y === S.Hidden && o.current) {
      if (v && T !== "visible") {
        V("visible");
        return;
      }
      return ae(T, { hidden: () => N(o), visible: () => x(o) });
    }
  }, [T, o, x, N, v, Y]);
  let W = le();
  L(() => {
    if (g && W && T === "visible" && o.current === null) throw new Error("Did you forget to passthrough the `ref` to the actual DOM node?");
  }, [o, T, W, g]);
  let ve = _ && !Z, J = Z && v && _, k = C(!1), D = ce(() => {
    k.current || (V("hidden"), N(o));
  }, q), ee = E((B) => {
    k.current = !0;
    let I = B ? "enter" : "leave";
    D.onStart(o, I, (A) => {
      A === "enter" ? y == null || y() : A === "leave" && (R == null || R());
    });
  }), re = E((B) => {
    let I = B ? "enter" : "leave";
    k.current = !1, D.onStop(o, I, (A) => {
      A === "enter" ? f == null || f() : A === "leave" && (h == null || h());
    }), I === "leave" && !K(D) && (V("hidden"), N(o));
  });
  ge(() => {
    g && w || (ee(v), re(v));
  }, [v, g, w]);
  let he = !(!w || !g || !W || ve), [, u] = we(he, $, v, { start: ee, end: re }), pe = ye({ ref: P, className: ((a = Pe(l.className, J && c, J && m, u.enter && c, u.enter && u.closed && m, u.enter && !u.closed && p, u.leave && i, u.leave && !u.closed && t, u.leave && u.closed && s, !u.transition && v && b)) == null ? void 0 : a.trim()) || void 0, ...Re(u) }), O = 0;
  T === "visible" && (O |= F.Open), T === "hidden" && (O |= F.Closed), u.enter && (O |= F.Opening), u.leave && (O |= F.Closing);
  let be = oe();
  return d.createElement(z.Provider, { value: D }, d.createElement($e, { value: O }, be({ ourProps: pe, theirProps: l, defaultTag: de, features: fe, visible: T === "visible", name: "Transition.Child" })));
}
function Le(e, r) {
  let { show: n, appear: a = !1, unmount: w = !0, ...y } = e, f = C(null), R = ue(e), h = ie(...R ? [f, r] : r === null ? [] : [r]);
  le();
  let c = se();
  if (n === void 0 && c !== null && (n = (c & F.Open) === F.Open), n === void 0) throw new Error("A <Transition /> is used but it is missing a `show={true | false}` prop.");
  let [m, p] = M(n ? "visible" : "hidden"), b = ce(() => {
    n || p("hidden");
  }), [i, t] = M(!0), s = C([n]);
  L(() => {
    i !== !1 && s.current[s.current.length - 1] !== n && (s.current.push(n), t(!1));
  }, [s, n]);
  let l = ne(() => ({ show: n, appear: a, initial: i }), [n, a, i]);
  L(() => {
    n ? p("visible") : !K(b) && f.current !== null && p("hidden");
  }, [n, b]);
  let $ = { unmount: w }, H = E(() => {
    var P;
    i && t(!1), (P = e.beforeEnter) == null || P.call(e);
  }), o = E(() => {
    var P;
    i && t(!1), (P = e.beforeLeave) == null || P.call(e);
  }), g = oe();
  return d.createElement(z.Provider, { value: b }, d.createElement(j.Provider, { value: l }, g({ ourProps: { ...$, as: U, children: d.createElement(me, { ref: h, ...$, ...y, beforeEnter: H, beforeLeave: o }) }, theirProps: {}, defaultTag: U, features: fe, visible: m === "visible", name: "Transition" })));
}
function xe(e, r) {
  let n = Q(j) !== null, a = se() !== null;
  return d.createElement(d.Fragment, null, !n && a ? d.createElement(G, { ref: r, ...e }) : d.createElement(me, { ref: r, ...e }));
}
let G = X(Le), me = X(Ae), Ne = X(xe), Xe = Object.assign(G, { Child: Ne, Root: G });
export {
  Xe as Transition,
  Ne as TransitionChild
};
