// Terminal — mini games and effects for easter eggs.
// Snake + hangman + ascii steam locomotive animation.

window.TERM_GAMES = (() => {
  const C = window.TERM_PALETTE;
  const plain = (t) => ({ type: 'span', text: t });
  const span = (color, text) => ({ type: 'span', color, text });
  const line = (...parts) => ({ type: 'line', parts });

  // ——— sl: animated ASCII train that drifts across the output ———
  const trainFrames = (() => {
    const engine = [
      '      ====        ________                ___________ ',
      '  _D _|  |_______/        \\__I_I_____===__|_________| ',
      '   |(_)---  |   H\\________/ |   |        =|___ ___|   ',
      '   /     |  |   H  |  |     |   |         ||_| |_||   ',
      '  |      |  |   H  |__--------------------| [___] |   ',
      '  | ________|___H__/__|_____/[][]~\\_______|       |   ',
      '  |/ |   |-----------I_____I [][] []  D   |=======|__ ',
      '__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__ ',
      ' |/-=|___|=    ||    ||    ||    |_____/~\\___/        ',
      '  \\_/      \\O=====O=====O=====O_/      \\_/            ',
    ];
    const width = 80;
    const frames = [];
    for (let off = width; off > -engine[0].length; off -= 4) {
      frames.push(engine.map((r) => {
        if (off >= 0) return ' '.repeat(off) + r.slice(0, Math.max(0, width - off));
        return r.slice(-off, -off + width);
      }));
    }
    return frames;
  })();

  function sl(print, done) {
    let i = 0;
    const id = Math.random().toString(36).slice(2, 8);
    print({ type: 'block', id, color: C.yellow, lines: trainFrames[0] });
    const t = setInterval(() => {
      i++;
      if (i >= trainFrames.length) { clearInterval(t); done(); return; }
      print({ type: 'update', id, color: C.yellow, lines: trainFrames[i] });
    }, 120);
    return () => clearInterval(t);
  }

  // ——— cowsay ———
  function cowsay(msg) {
    const text = msg || 'moo.';
    const top = ' ' + '_'.repeat(text.length + 2);
    const bot = ' ' + '-'.repeat(text.length + 2);
    return [
      line(span(C.yellow, top)),
      line(span(C.yellow, `< ${text} >`)),
      line(span(C.yellow, bot)),
      line(span(C.fg, '        \\   ^__^')),
      line(span(C.fg, '         \\  (oo)\\_______')),
      line(span(C.fg, '            (__)\\       )\\/\\')),
      line(span(C.fg, '                ||----w |')),
      line(span(C.fg, '                ||     ||')),
    ];
  }

  // ——— rm -rf / fake disaster ———
  function rmrfSteps() {
    const steps = [
      'rm: descending into /bin ...',
      'rm: descending into /boot ...',
      'rm: descending into /etc ...',
      'rm: descending into /home ...',
      'rm: WARNING: this is the production filesystem.',
      'rm: proceeding anyway because you said sudo.',
      'kernel: filesystem integrity: ⚠ compromised',
      'systemd: killing init. good luck.',
      'PANIC: attempted to kill init!',
      '',
      '(just kidding. nothing happened. breathe.)',
    ];
    return steps;
  }

  // ——— snake game (inline, arrow keys, Esc to quit) ———
  function makeSnake() {
    const W = 30, H = 14;
    let snake = [[10, 7], [9, 7], [8, 7]];
    let dir = [1, 0];
    let food = [20, 7];
    let dead = false, score = 0, won = false;
    const step = () => {
      if (dead) return;
      const [hx, hy] = snake[0];
      const nx = hx + dir[0], ny = hy + dir[1];
      if (nx < 0 || ny < 0 || nx >= W || ny >= H) { dead = true; return; }
      if (snake.some(([x, y]) => x === nx && y === ny)) { dead = true; return; }
      snake.unshift([nx, ny]);
      if (nx === food[0] && ny === food[1]) {
        score++;
        let tries = 0;
        do {
          food = [Math.floor(Math.random() * W), Math.floor(Math.random() * H)];
          tries++;
        } while (snake.some(([x, y]) => x === food[0] && y === food[1]) && tries < 100);
        if (score >= 20) { won = true; dead = true; }
      } else snake.pop();
    };
    const render = () => {
      const g = Array.from({ length: H }, () => Array(W).fill(' '));
      snake.forEach(([x, y], i) => { g[y][x] = i === 0 ? '@' : 'o'; });
      g[food[1]][food[0]] = '*';
      const top = '┌' + '─'.repeat(W) + '┐';
      const bot = '└' + '─'.repeat(W) + '┘';
      const rows = g.map((r) => '│' + r.join('') + '│');
      return [top, ...rows, bot, `score: ${score}${dead ? (won ? '  · YOU WIN — esc to quit' : '  · game over — esc to quit') : ''}`];
    };
    const setDir = (k) => {
      const m = { ArrowUp: [0, -1], ArrowDown: [0, 1], ArrowLeft: [-1, 0], ArrowRight: [1, 0] };
      const nd = m[k]; if (!nd) return;
      if (nd[0] === -dir[0] && nd[1] === -dir[1]) return;
      dir = nd;
    };
    return { step, render, setDir, isDead: () => dead };
  }

  // ——— hangman ———
  const hangmanArt = [
`  +---+
  |   |
      |
      |
      |
      |
=========`,
`  +---+
  |   |
  O   |
      |
      |
      |
=========`,
`  +---+
  |   |
  O   |
  |   |
      |
      |
=========`,
`  +---+
  |   |
  O   |
 /|   |
      |
      |
=========`,
`  +---+
  |   |
  O   |
 /|\\  |
      |
      |
=========`,
`  +---+
  |   |
  O   |
 /|\\  |
 /    |
      |
=========`,
`  +---+
  |   |
  O   |
 /|\\  |
 / \\  |
      |
=========`,
  ];
  const hangmanWords = ['runbook', 'kernel', 'incident', 'terraform', 'kubernetes', 'observability', 'deploy', 'mainframe', 'systemd', 'segfault'];
  function makeHangman() {
    const word = hangmanWords[Math.floor(Math.random() * hangmanWords.length)];
    const guessed = new Set();
    let wrong = 0, done = false, won = false;
    const guess = (ch) => {
      ch = ch.toLowerCase();
      if (done || !/^[a-z]$/.test(ch) || guessed.has(ch)) return;
      guessed.add(ch);
      if (!word.includes(ch)) wrong++;
      if (wrong >= 6) done = true;
      else if ([...word].every((c) => guessed.has(c))) { done = true; won = true; }
    };
    const render = () => {
      const art = hangmanArt[Math.min(wrong, 6)].split('\n');
      const reveal = [...word].map((c) => guessed.has(c) ? c : '_').join(' ');
      const used = [...guessed].sort().join(' ');
      return [
        ...art,
        '',
        'word: ' + reveal,
        'used: ' + used,
        done ? (won ? 'you win. type any key to exit.' : `hanged. word was "${word}". type any key to exit.`) : 'type a letter · esc to quit',
      ];
    };
    return { guess, render, isDone: () => done };
  }

  return { sl, cowsay, rmrfSteps, makeSnake, makeHangman };
})();
