// loading-indicator.jsx
// Trillic compact loading indicator: traces "Trillic" on a 3x3 grid in a tight loop.
// Strip-down of the cosmic loading-pattern — no celestial circles, no HUD, no finale.
// Suitable for inline placement (e.g. a "drafting…" state, an auth spinner, a button).

const { useMemo: useMemoLI } = React;

function readTokenLI(name, fallback) {
  if (typeof window === 'undefined') return fallback;
  const v = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
  return v || fallback;
}

const THEME_LI = {
  bg:        readTokenLI('--background',     '#FAF5EC'),
  ink:       readTokenLI('--brand-gold',     '#CDA973'),
  inkBright: readTokenLI('--brand-gold-300', '#D9BC83'),
  inkSoft:   'color-mix(in oklab, ' + readTokenLI('--brand-gold', '#CDA973') + ' 22%, transparent)',
  inkLine:   'color-mix(in oklab, ' + readTokenLI('--brand-gold', '#CDA973') + ' 35%, transparent)',
};

const NODE_XY_LI = (i) => ({ col: i % 3, row: Math.floor(i / 3) });

// Letters traced as polylines on the 3x3 grid (same paths as the cosmic version).
const LETTERS_LI = [
  { ch: 'T', path: [0, 1, 2, 1, 4, 7] },
  { ch: 'r', path: [6, 3, 0, 1, 2] },
  { ch: 'I', path: [0, 1, 2, 1, 4, 7, 6, 7, 8] },
  { ch: 'L', path: [0, 3, 6, 7, 8] },
  { ch: 'L', path: [0, 3, 6, 7, 8] },
  { ch: 'I', path: [0, 1, 2, 1, 4, 7, 6, 7, 8] },
  { ch: 'C', path: [2, 1, 0, 3, 6, 7, 8] },
];

function polyMetaLI(path) {
  const segs = [];
  let total = 0;
  for (let i = 0; i < path.length - 1; i++) {
    const a = NODE_XY_LI(path[i]);
    const b = NODE_XY_LI(path[i + 1]);
    const len = Math.hypot(b.col - a.col, b.row - a.row);
    segs.push({ from: a, to: b, len, t0: total, t1: total + len });
    total += len;
  }
  segs.forEach((s) => { s.t0 /= total; s.t1 /= total; });
  return { segs, total };
}

function pointAtLI(meta, f) {
  if (f <= 0) return { x: meta.segs[0].from.col, y: meta.segs[0].from.row };
  if (f >= 1) {
    const last = meta.segs[meta.segs.length - 1];
    return { x: last.to.col, y: last.to.row };
  }
  for (const s of meta.segs) {
    if (f >= s.t0 && f <= s.t1) {
      const local = (s.t1 === s.t0) ? 0 : (f - s.t0) / (s.t1 - s.t0);
      return {
        x: s.from.col + (s.to.col - s.from.col) * local,
        y: s.from.row + (s.to.row - s.from.row) * local,
      };
    }
  }
  const last = meta.segs[meta.segs.length - 1];
  return { x: last.to.col, y: last.to.row };
}

function partialPointsLI(path, meta, f) {
  if (f <= 0) return [];
  const pts = [{ x: NODE_XY_LI(path[0]).col, y: NODE_XY_LI(path[0]).row }];
  if (f >= 1) {
    for (let i = 1; i < path.length; i++) {
      pts.push({ x: NODE_XY_LI(path[i]).col, y: NODE_XY_LI(path[i]).row });
    }
    return pts;
  }
  for (const s of meta.segs) {
    if (f >= s.t1) {
      pts.push({ x: s.to.col, y: s.to.row });
    } else if (f > s.t0) {
      const local = (f - s.t0) / (s.t1 - s.t0);
      pts.push({
        x: s.from.col + (s.to.col - s.from.col) * local,
        y: s.from.row + (s.to.row - s.from.row) * local,
      });
      break;
    }
  }
  return pts;
}

function visitedNodesLI(path, meta, f) {
  const visited = new Set();
  if (f <= 0) return visited;
  visited.add(path[0]);
  for (let i = 0; i < meta.segs.length; i++) {
    if (f >= meta.segs[i].t1 - 1e-6) visited.add(path[i + 1]);
  }
  return visited;
}

function GridDots({ cx, cy, cell }) {
  const toX = (gx) => cx + (gx - 1) * cell;
  const toY = (gy) => cy + (gy - 1) * cell;
  return (
    <g>
      {Array.from({ length: 9 }).map((_, i) => {
        const { col, row } = NODE_XY_LI(i);
        return (
          <g key={i}>
            <circle cx={toX(col)} cy={toY(row)} r={10} fill="none" stroke={THEME_LI.inkSoft} strokeWidth="1" />
            <circle cx={toX(col)} cy={toY(row)} r={3.5} fill={THEME_LI.inkSoft} />
          </g>
        );
      })}
    </g>
  );
}

function StrokeLI({ cx, cy, cell, progress, path, opacity = 1 }) {
  const meta = useMemoLI(() => polyMetaLI(path), [path]);
  const pts = partialPointsLI(path, meta, progress);
  const head = pointAtLI(meta, progress);
  const visited = visitedNodesLI(path, meta, progress);
  const toX = (gx) => cx + (gx - 1) * cell;
  const toY = (gy) => cy + (gy - 1) * cell;
  const linePts = pts.map((p) => `${toX(p.x).toFixed(2)},${toY(p.y).toFixed(2)}`).join(' ');
  return (
    <g style={{ opacity }}>
      {Array.from(visited).map((i) => {
        const { col, row } = NODE_XY_LI(i);
        const x = toX(col), y = toY(row);
        return (
          <g key={i}>
            <circle cx={x} cy={y} r={16} fill="none" stroke={THEME_LI.inkBright} strokeWidth="1" opacity="0.45" />
            <circle cx={x} cy={y} r={5.5} fill={THEME_LI.inkBright} />
          </g>
        );
      })}
      {pts.length >= 2 && (
        <polyline
          points={linePts}
          fill="none"
          stroke={THEME_LI.ink}
          strokeWidth="3"
          strokeLinecap="round"
          strokeLinejoin="round"
          opacity="0.95"
        />
      )}
      {progress > 0 && progress < 1 && (
        <>
          <circle cx={toX(head.x)} cy={toY(head.y)} r={9} fill="none" stroke={THEME_LI.inkBright} strokeWidth="1.2" opacity="0.7" />
          <circle cx={toX(head.x)} cy={toY(head.y)} r={4} fill={THEME_LI.inkBright} />
        </>
      )}
    </g>
  );
}

function LetterSlotLI({ start, drawDur, holdDur, exitDur, idx, cx, cy, cell }) {
  return (
    <Sprite start={start} end={start + drawDur + holdDur + exitDur}>
      {({ localTime }) => {
        let progress = 0, op = 1;
        if (localTime < drawDur) {
          progress = Easing.easeInOutCubic(clamp(localTime / drawDur, 0, 1));
        } else if (localTime < drawDur + holdDur) {
          progress = 1;
        } else {
          progress = 1;
          op = 1 - Easing.easeInQuad(clamp((localTime - drawDur - holdDur) / exitDur, 0, 1));
        }
        return (
          <StrokeLI
            cx={cx} cy={cy} cell={cell}
            progress={progress}
            path={LETTERS_LI[idx].path}
            opacity={op}
          />
        );
      }}
    </Sprite>
  );
}

function TrillicLoadingIndicator() {
  const W = 240, H = 240;
  const CX = W / 2, CY = H / 2;
  const CELL = 56;

  // Tighter than the cosmic version — better suited for a loop indicator
  const drawDur = 0.55;
  const holdDur = 0.10;
  const exitDur = 0.22;
  const perLetter = drawDur + holdDur + exitDur;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width={W} height={H} style={{ position: 'absolute', inset: 0, display: 'block' }}>
      <g transform={`rotate(45 ${CX} ${CY})`}>
        <GridDots cx={CX} cy={CY} cell={CELL} />
        {LETTERS_LI.map((L, i) => (
          <LetterSlotLI
            key={i}
            idx={i}
            start={i * perLetter}
            drawDur={drawDur} holdDur={holdDur} exitDur={exitDur}
            cx={CX} cy={CY} cell={CELL}
          />
        ))}
      </g>
    </svg>
  );
}

window.TrillicLoadingIndicator = TrillicLoadingIndicator;
window.TRILLIC_LOADING_INDICATOR_TOTAL = (0.55 + 0.10 + 0.22) * 7; // ~6.09s loop
