// Text to Handwriting — render text onto A4-ratio canvas with handwriting fonts, custom ink, paper styles.

window.TOOL_HANDLERS['text-to-handwriting'] = function TextToHandwritingTool() {
  const FONTS = ['Caveat', 'Dancing Script', 'Indie Flower', 'Gloria Hallelujah', 'Kalam'];
  const PAPER_TYPES = ['White', 'Lined', 'Grid'];
  const PAGE_W = 794;
  const PAGE_H = 1123;
  const MARGIN_X = 60;
  const MARGIN_TOP = 80;
  const MARGIN_BOTTOM = 60;

  const [text, setText] = React.useState('The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs.');
  const [font, setFont] = React.useState('Caveat');
  const [inkColor, setInkColor] = React.useState('#1a237e');
  const [fontSize, setFontSize] = React.useState(20);
  const [lineHeight, setLineHeight] = React.useState(2);
  const [paper, setPaper] = React.useState('Lined');
  const [pages, setPages] = React.useState([]);   // array of data URLs
  const [fontsLoaded, setFontsLoaded] = React.useState(false);

  // Load all Google Fonts on mount
  React.useEffect(() => {
    const loaded = [];
    FONTS.forEach((f) => {
      const id = 'gfont-' + f.replace(/\s+/g, '-');
      if (document.getElementById(id)) { loaded.push(true); return; }
      const link = document.createElement('link');
      link.id = id;
      link.href = 'https://fonts.googleapis.com/css2?family=' + encodeURIComponent(f) + '&display=swap';
      link.rel = 'stylesheet';
      document.head.appendChild(link);
      loaded.push(true);
    });
    // Allow fonts time to load
    setTimeout(() => setFontsLoaded(true), 800);
  }, []);

  // Draw pages whenever inputs change
  React.useEffect(() => {
    if (!fontsLoaded) return;
    const lh = fontSize * lineHeight;
    const maxW = PAGE_W - MARGIN_X * 2;
    const usableH = PAGE_H - MARGIN_TOP - MARGIN_BOTTOM;

    // Split text into wrapped lines
    const measureCanvas = document.createElement('canvas');
    const mctx = measureCanvas.getContext('2d');
    mctx.font = fontSize + 'px "' + font + '", cursive';

    const rawLines = text.split('\n');
    const allLines = [];
    rawLines.forEach((rawLine) => {
      if (rawLine.trim() === '') { allLines.push(''); return; }
      const words = rawLine.split(/\s+/);
      let cur = '';
      words.forEach((w) => {
        const test = cur ? cur + ' ' + w : w;
        if (mctx.measureText(test).width > maxW && cur) {
          allLines.push(cur);
          cur = w;
        } else {
          cur = test;
        }
      });
      if (cur) allLines.push(cur);
    });

    // Paginate
    const linesPerPage = Math.max(1, Math.floor(usableH / lh));
    const pageChunks = [];
    for (let i = 0; i < allLines.length; i += linesPerPage) {
      pageChunks.push(allLines.slice(i, i + linesPerPage));
    }
    if (pageChunks.length === 0) pageChunks.push([]);

    // Render each page
    const dataUrls = pageChunks.map((lines) => {
      const c = document.createElement('canvas');
      c.width = PAGE_W; c.height = PAGE_H;
      const ctx = c.getContext('2d');

      // Paper background
      ctx.fillStyle = '#fffef5';
      ctx.fillRect(0, 0, PAGE_W, PAGE_H);

      if (paper === 'Lined') {
        ctx.strokeStyle = 'rgba(100, 149, 237, 0.25)';
        ctx.lineWidth = 1;
        for (let y = MARGIN_TOP; y < PAGE_H - MARGIN_BOTTOM; y += lh) {
          ctx.beginPath();
          ctx.moveTo(MARGIN_X - 10, y);
          ctx.lineTo(PAGE_W - MARGIN_X + 10, y);
          ctx.stroke();
        }
        // Red margin line
        ctx.strokeStyle = 'rgba(220, 80, 80, 0.35)';
        ctx.lineWidth = 1.5;
        ctx.beginPath();
        ctx.moveTo(MARGIN_X - 20, 0);
        ctx.lineTo(MARGIN_X - 20, PAGE_H);
        ctx.stroke();
      } else if (paper === 'Grid') {
        ctx.strokeStyle = 'rgba(150, 150, 150, 0.18)';
        ctx.lineWidth = 0.5;
        const gridSize = 20;
        for (let x = MARGIN_X; x < PAGE_W - MARGIN_X; x += gridSize) {
          ctx.beginPath(); ctx.moveTo(x, MARGIN_TOP); ctx.lineTo(x, PAGE_H - MARGIN_BOTTOM); ctx.stroke();
        }
        for (let y = MARGIN_TOP; y < PAGE_H - MARGIN_BOTTOM; y += gridSize) {
          ctx.beginPath(); ctx.moveTo(MARGIN_X, y); ctx.lineTo(PAGE_W - MARGIN_X, y); ctx.stroke();
        }
      }

      // Render text
      ctx.font = fontSize + 'px "' + font + '", cursive';
      ctx.fillStyle = inkColor;
      ctx.textBaseline = 'top';
      lines.forEach((line, i) => {
        const y = MARGIN_TOP + i * lh + (lh - fontSize) * 0.3;
        ctx.fillText(line, MARGIN_X, y);
      });

      return c.toDataURL('image/png');
    });

    setPages(dataUrls);
  }, [text, font, inkColor, fontSize, lineHeight, paper, fontsLoaded]);

  const download = React.useCallback(async () => {
    if (pages.length === 0) return;
    if (pages.length === 1) {
      // Single page: download PNG directly
      const resp = await fetch(pages[0]);
      const blob = await resp.blob();
      window.downloadBlob(blob, 'handwriting.png');
    } else {
      // Multi-page: zip them
      await window.loadScript('https://cdn.jsdelivr.net/npm/fflate@0.8.2/umd/index.js');
      const files = {};
      for (let i = 0; i < pages.length; i++) {
        const resp = await fetch(pages[i]);
        const buf = await resp.arrayBuffer();
        files['page-' + String(i + 1).padStart(2, '0') + '.png'] = new Uint8Array(buf);
      }
      const zipped = fflate.zipSync(files, { level: 0 });
      window.downloadBlob(new Blob([zipped], { type: 'application/zip' }), 'handwriting-pages.zip');
    }
    window.mmTrackComplete?.('text-to-handwriting', { pages: pages.length });
  }, [pages]);

  return (
    <div className="mini-tool">
      <label className="mini-label">Your text</label>
      <textarea
        className="mini-input mini-textarea"
        style={{ minHeight: 120 }}
        placeholder="Type or paste the text you want in handwriting..."
        value={text}
        onChange={(e) => setText(e.target.value)}
      />

      <div className="mini-row" style={{ marginTop: 14, flexWrap: 'wrap' }}>
        <div className="mini-field" style={{ flex: '1 1 160px' }}>
          <label className="mini-label">Font</label>
          <select className="mini-input" value={font} onChange={(e) => setFont(e.target.value)}>
            {FONTS.map((f) => (
              <option key={f} value={f} style={{ fontFamily: '"' + f + '", cursive' }}>{f}</option>
            ))}
          </select>
        </div>
        <div className="mini-field" style={{ flex: '0 0 80px' }}>
          <label className="mini-label">Ink color</label>
          <input type="color" className="mini-input" value={inkColor}
            onChange={(e) => setInkColor(e.target.value)} style={{ height: 36, padding: 4 }} />
        </div>
        <div className="mini-field" style={{ flex: '1 1 120px' }}>
          <label className="mini-label">Paper</label>
          <select className="mini-input" value={paper} onChange={(e) => setPaper(e.target.value)}>
            {PAPER_TYPES.map((p) => <option key={p} value={p}>{p}</option>)}
          </select>
        </div>
      </div>

      <div className="mini-row" style={{ marginTop: 10 }}>
        <div className="mini-field" style={{ flex: 1 }}>
          <label className="mini-label">Font size: {fontSize}px</label>
          <input type="range" className="cmp-slider" min="14" max="32" step="1"
            value={fontSize} onChange={(e) => setFontSize(Number(e.target.value))} />
        </div>
        <div className="mini-field" style={{ flex: 1 }}>
          <label className="mini-label">Line height: {lineHeight.toFixed(1)}</label>
          <input type="range" className="cmp-slider" min="1.5" max="3" step="0.1"
            value={lineHeight} onChange={(e) => setLineHeight(Number(e.target.value))} />
        </div>
      </div>

      {/* Preview */}
      {pages.length > 0 && (
        <div style={{ marginTop: 18 }}>
          <label className="mini-label">Preview ({pages.length} page{pages.length > 1 ? 's' : ''})</label>
          <div style={{
            display: 'flex', flexWrap: 'wrap', gap: 12, justifyContent: 'center', marginTop: 8,
            padding: 16, background: 'var(--id-surface)', borderRadius: 12, border: '1px solid var(--id-border)'
          }}>
            {pages.map((url, i) => (
              <img key={i} src={url} alt={'Page ' + (i + 1)}
                style={{ maxHeight: 340, border: '1px solid var(--id-border)', borderRadius: 6,
                  boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }} />
            ))}
          </div>
        </div>
      )}

      <div className="cmp-actions">
        <button className="btn btn-primary" onClick={download} disabled={pages.length === 0 || !text.trim()}>
          <window.Icon name="download" size={16} />
          {pages.length > 1 ? 'Download ZIP (' + pages.length + ' pages)' : 'Download PNG'}
        </button>
      </div>
    </div>
  );
};
