import { RangeSetBuilder as S } from "@codemirror/state";
import { ViewPlugin as B, Decoration as b, EditorView as w, WidgetType as P } from "@codemirror/view";
const y = typeof window < "u" ? window : null, m = typeof document < "u" ? document : null, G = (y == null ? void 0 : y.__CM_VERTICAL_ORIGINALS__) || {
  elementGBCR: Element.prototype.getBoundingClientRect,
  rangeGBCR: Range.prototype.getBoundingClientRect,
  rangeGetClientRects: Range.prototype.getClientRects,
  caretRange: m != null && m.caretRangeFromPoint ? m.caretRangeFromPoint.bind(m) : null,
  // @ts-ignore
  caretPosition: m != null && m.caretPositionFromPoint ? m.caretPositionFromPoint.bind(m) : null
};
y && !y.__CM_VERTICAL_ORIGINALS__ && (y.__CM_VERTICAL_ORIGINALS__ = G);
const i = G;
let p = !1, l = null, C = 0, E = 0;
function L() {
  if (!l) return null;
  const t = getComputedStyle(l);
  return !t.transform || t.transform === "none" ? null : new DOMMatrix(t.transform).inverse();
}
function D() {
  if (!(l != null && l.parentElement)) return null;
  const t = i.elementGBCR.call(l.parentElement);
  return { x: t.left, y: t.top };
}
function R(t) {
  const e = L(), n = D();
  if (!e || !n) return t;
  const s = [
    { x: t.left, y: t.top },
    { x: t.right, y: t.top },
    { x: t.left, y: t.bottom },
    { x: t.right, y: t.bottom }
  ].map((c) => {
    const o = e.transformPoint(new DOMPoint(c.x - n.x, c.y - n.y));
    return { x: o.x + n.x, y: o.y + n.y };
  }), a = Math.min(...s.map((c) => c.x)), d = Math.min(...s.map((c) => c.y)), u = Math.max(...s.map((c) => c.x)) - a, f = Math.max(...s.map((c) => c.y)) - d;
  return new DOMRect(a, d, u, f);
}
function F(t, e) {
  const n = L(), s = D();
  if (!n || !s) return { x: t, y: e };
  const a = n.transformPoint(new DOMPoint(t - s.x, e - s.y));
  return { x: a.x + s.x, y: a.y + s.y };
}
function v(t) {
  if (!p || !l) return;
  C = t.clientX, E = t.clientY;
  const e = F(t.clientX, t.clientY);
  Object.defineProperty(t, "clientX", { value: e.x, configurable: !0 }), Object.defineProperty(t, "clientY", { value: e.y, configurable: !0 }), Object.defineProperty(t, "pageX", { value: e.x + window.scrollX, configurable: !0 }), Object.defineProperty(t, "pageY", { value: e.y + window.scrollY, configurable: !0 });
}
let x = !1;
function Q() {
  x || (x = !0, Element.prototype.getBoundingClientRect = function() {
    const t = i.elementGBCR.call(this);
    return !p || !l || !l.contains(this) ? t : R(t);
  }, Range.prototype.getBoundingClientRect = function() {
    const t = i.rangeGBCR.call(this);
    if (!p || !l) return t;
    const e = this.commonAncestorContainer, n = e.nodeType === Node.ELEMENT_NODE ? e : e.parentElement;
    return !n || !l.contains(n) ? t : R(t);
  }, Range.prototype.getClientRects = function() {
    const t = i.rangeGetClientRects.call(this);
    if (!p || !l) return t;
    const e = this.commonAncestorContainer, n = e.nodeType === Node.ELEMENT_NODE ? e : e.parentElement;
    if (!n || !l.contains(n)) return t;
    const s = [];
    for (let a = 0; a < t.length; a++) s.push(R(t[a]));
    return Object.assign(s, {
      item: (a) => s[a] ?? null
    });
  }, i.caretRange && (document.caretRangeFromPoint = (t, e) => p && i.caretRange ? i.caretRange(C, E) : i.caretRange ? i.caretRange(t, e) : null), i.caretPosition && (document.caretPositionFromPoint = (t, e) => p && i.caretPosition ? i.caretPosition(C, E) : i.caretPosition ? i.caretPosition(t, e) : null));
}
function tt() {
  x && (x = !1, Element.prototype.getBoundingClientRect = i.elementGBCR, Range.prototype.getBoundingClientRect = i.rangeGBCR, Range.prototype.getClientRects = i.rangeGetClientRects, i.caretRange && (document.caretRangeFromPoint = i.caretRange), i.caretPosition && (document.caretPositionFromPoint = i.caretPosition));
}
function et(t, e) {
  p = t, l = e;
}
function nt(t) {
  const e = ["mousedown", "mousemove", "mouseup", "click"];
  return e.forEach((n) => t.addEventListener(n, v, { capture: !0 })), () => e.forEach((n) => t.removeEventListener(n, v, { capture: !0 }));
}
function ot(t) {
  return i.elementGBCR.call(t);
}
class N extends P {
  constructor(e) {
    super(), this.text = e;
  }
  toDOM() {
    let e = document.createElement("span");
    return e.className = "cm-tcy", e.textContent = this.text, e;
  }
}
const V = B.fromClass(class {
  constructor(t) {
    this.decorations = this.buildDeco(t);
  }
  update(t) {
    (t.docChanged || t.viewportChanged || t.selectionSet) && (this.decorations = this.buildDeco(t.view));
  }
  buildDeco(t) {
    const e = new S(), { selection: n } = t.state, s = new RegExp("(?<![A-Za-z0-9])([A-Za-z0-9]{2}|[!?]{1,2})(?![A-Za-z0-9])", "g");
    for (const { from: a, to: d } of t.visibleRanges) {
      let u = a;
      for (; u <= d; ) {
        const f = t.state.doc.lineAt(u), c = f.text;
        let o;
        const r = Math.max(0, a - f.from), h = Math.min(f.length, d - f.from);
        for (s.lastIndex = r; (o = s.exec(c)) !== null && !(o.index >= h); ) {
          const g = f.from + o.index, _ = g + o[0].length;
          n.ranges.some((M) => M.from <= _ && M.to >= g) || e.add(g, _, b.replace({ widget: new N(o[0]) }));
        }
        u = f.to + 1;
      }
    }
    return e.finish();
  }
}, {
  decorations: (t) => t.decorations
}), Y = w.baseTheme({
  ".cm-tcy": {
    display: "inline-block",
    transform: "rotate(-90deg)",
    transformOrigin: "center center",
    lineHeight: "1",
    margin: "0 2px"
  }
}), z = [V, Y];
class X extends P {
  constructor(e, n) {
    super(), this.baseText = e, this.rubyText = n;
  }
  toDOM() {
    const e = document.createElement("ruby");
    e.textContent = this.baseText;
    const n = document.createElement("rt");
    return n.textContent = this.rubyText, e.appendChild(n), e;
  }
  ignoreEvent() {
    return !1;
  }
}
const T = /\|([^《]+)《([^》]+)》/g, I = /([一-龠々〆ヵヶ]+)《([^》]+)》/g, O = /《《([^》]+)》》/g;
class k extends P {
  constructor(e) {
    super(), this.text = e;
  }
  toDOM() {
    let e = document.createElement("span");
    return e.className = "cm-emphasis", e.textContent = this.text, e;
  }
}
const j = B.fromClass(
  class {
    constructor(t) {
      this.decorations = this.buildDeco(t);
    }
    update(t) {
      (t.docChanged || t.selectionSet || t.viewportChanged) && (this.decorations = this.buildDeco(t.view));
    }
    buildDeco(t) {
      const e = new S(), n = t.state.selection.ranges;
      for (const { from: s, to: a } of t.visibleRanges) {
        let d = s;
        for (; d <= a; ) {
          const u = t.state.doc.lineAt(d), f = u.text, c = [];
          T.lastIndex = 0;
          let o;
          for (; (o = T.exec(f)) !== null; )
            c.push({
              from: u.from + o.index,
              to: u.from + o.index + o[0].length,
              type: "ruby",
              data: { base: o[1], ruby: o[2] }
            });
          for (I.lastIndex = 0; (o = I.exec(f)) !== null; ) {
            const r = u.from + o.index, h = r + o[0].length;
            c.some((g) => r < g.to && h > g.from) || c.push({
              from: r,
              to: h,
              type: "ruby",
              data: { base: o[1], ruby: o[2] }
            });
          }
          for (O.lastIndex = 0; (o = O.exec(f)) !== null; )
            c.push({
              from: u.from + o.index,
              to: u.from + o.index + o[0].length,
              type: "emphasis",
              data: o[1]
            });
          c.sort((r, h) => r.from - h.from);
          for (const r of c)
            n.some((g) => g.from <= r.to && g.to >= r.from) || (r.type === "ruby" && typeof r.data == "object" ? e.add(r.from, r.to, b.replace({ widget: new X(r.data.base, r.data.ruby) })) : r.type === "emphasis" && typeof r.data == "string" && e.add(r.from, r.to, b.replace({ widget: new k(r.data) })));
          d = u.to + 1;
        }
      }
      return e.finish();
    }
  },
  {
    decorations: (t) => t.decorations
  }
), H = w.baseTheme({
  ruby: {
    position: "relative",
    display: "inline-flex",
    flexDirection: "column-reverse",
    verticalAlign: "bottom"
  },
  ".cm-emphasis": {
    textEmphasis: "filled dot",
    "-webkit-text-emphasis": "filled dot",
    textEmphasisPosition: "over right",
    "-webkit-text-emphasis-position": "over right"
  }
}), U = [j, H], W = (t = {}) => w.theme({
  "&": {
    height: "100%",
    width: "100%",
    fontSize: t.fontSize || "1.1rem",
    backgroundColor: "transparent",
    writingMode: "horizontal-tb"
    // Forced horizontal context for reliable coordinate logic
  },
  ".cm-scroller": {
    overflowX: "auto",
    overflowY: "auto"
  },
  ".cm-content": {
    padding: "40px",
    minHeight: "100%",
    whiteSpace: "pre-wrap",
    wordBreak: "break-all",
    color: t.textColor || "inherit",
    fontFamily: t.fontFamily || "serif"
  },
  ".cm-line": {
    fontSize: "inherit",
    lineHeight: "1.8"
    // Stable line height for vertical grid
  },
  // Prevent syntax highlighting from changing font metrics
  ".cm-content *": {
    fontSize: "inherit !important",
    fontWeight: "inherit !important",
    lineHeight: "inherit !important"
  },
  ".cm-cursor": {
    borderLeft: "1.2px solid currentColor"
  }
}), Z = "STVerticalMincho", A = "cm-vertical-writing-font";
function $() {
  try {
    return new URL(
      /* @vite-ignore */
      "./fonts/STVerticalMincho.ttf",
      import.meta.url
    ).href;
  } catch {
    return "./fonts/STVerticalMincho.ttf";
  }
}
function it(t) {
  if (typeof document > "u" || document.getElementById(A))
    return;
  const e = t ?? $(), n = document.createElement("style");
  n.id = A, n.textContent = `
@font-face {
    font-family: '${Z}';
    src: url('${e}') format('truetype');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}
`, document.head.appendChild(n);
}
function rt(t) {
  const e = [
    W({
      fontFamily: t.fontFamily,
      fontSize: t.fontSize,
      textColor: t.textColor
    })
  ];
  return t.tcy !== !1 && e.push(z), t.ruby !== !1 && e.push(U), e;
}
export {
  nt as attachMouseListeners,
  ot as getPhysicalRect,
  it as injectFont,
  Q as installPatches,
  U as ruby,
  et as setupVertical,
  z as tcy,
  tt as uninstallPatches,
  rt as verticalWriting
};
