'use strict';
// Extract the Cyrillic "Э" (U+042D) and the digit "8" outlines from a grotesque
// font (LiberationSans = Arial-metric, matching the game's system-ui/Arial stack)
// and emit Lottie cubic-bezier contours, centred at the origin, y-down.
const opentype = require('opentype.js');
const fs = require('fs');

const FONT = process.argv[2] || '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf';
const b = fs.readFileSync(FONT);
const font = opentype.parse(b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength));
const FS = 1000; // em scale

function glyphContours(ch) {
  const p = font.charToGlyph(ch).getPath(0, 0, FS); // baseline at y=0, y-down
  const contours = [];
  let cur = null, prev = null;
  for (const c of p.commands) {
    if (c.type === 'M') {
      if (cur) contours.push(cur);
      cur = [{ v: [c.x, c.y], i: [c.x, c.y], o: [c.x, c.y] }];
      prev = { x: c.x, y: c.y };
    } else if (c.type === 'L') {
      cur.push({ v: [c.x, c.y], i: [c.x, c.y], o: [c.x, c.y] });
      prev = { x: c.x, y: c.y };
    } else if (c.type === 'C') {
      cur[cur.length - 1].o = [c.x1, c.y1];
      cur.push({ v: [c.x, c.y], i: [c.x2, c.y2], o: [c.x, c.y] });
      prev = { x: c.x, y: c.y };
    } else if (c.type === 'Q') {
      const c1 = [prev.x + 2 / 3 * (c.x1 - prev.x), prev.y + 2 / 3 * (c.y1 - prev.y)];
      const c2 = [c.x + 2 / 3 * (c.x1 - c.x), c.y + 2 / 3 * (c.y1 - c.y)];
      cur[cur.length - 1].o = c1;
      cur.push({ v: [c.x, c.y], i: c2, o: [c.x, c.y] });
      prev = { x: c.x, y: c.y };
    } else if (c.type === 'Z') {
      if (cur && cur.length > 1) {
        const last = cur[cur.length - 1], first = cur[0];
        if (Math.hypot(last.v[0] - first.v[0], last.v[1] - first.v[1]) < 1e-3) {
          first.i = last.i;            // fold the duplicate closing point into the first
          cur.pop();
        }
      }
      if (cur) { contours.push(cur); cur = null; }
    }
  }
  if (cur) contours.push(cur);

  let minx = Infinity, miny = Infinity, maxx = -Infinity, maxy = -Infinity;
  const out = contours.map(ct => {
    const v = [], i = [], o = [];
    ct.forEach(pt => {
      v.push(pt.v);
      i.push([pt.i[0] - pt.v[0], pt.i[1] - pt.v[1]]);
      o.push([pt.o[0] - pt.v[0], pt.o[1] - pt.v[1]]);
      minx = Math.min(minx, pt.v[0]); maxx = Math.max(maxx, pt.v[0]);
      miny = Math.min(miny, pt.v[1]); maxy = Math.max(maxy, pt.v[1]);
    });
    return { i, o, v, c: true };
  });
  return { contours: out, bbox: { x: minx, y: miny, w: maxx - minx, h: maxy - miny } };
}

const E = glyphContours('Э');
const D8 = glyphContours('8');
fs.writeFileSync('glyphs.json', JSON.stringify({ em: FS, E, D8 }));
console.log('Э bbox', E.bbox, 'contours', E.contours.map(c => c.v.length));
console.log('8 bbox', D8.bbox, 'contours', D8.contours.map(c => c.v.length));
