#!/usr/bin/env python3
"""Convert CJK subset from CID-keyed CFF/OTF to TrueType/TTF.

stb_truetype (used by ImGui) doesn't handle CID-keyed CFF fonts properly,
so we need glyf-based TrueType outlines instead.

Two approaches:
1. Direct CFF->TTF conversion via cu2qu (fontTools)
2. Download NotoSansSC-Regular.ttf (already TTF) and re-subset

This script tries approach 1 first, falls back to approach 2.
"""

import os
import sys
import json
import glob

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
FONT_DIR = os.path.join(PROJECT_ROOT, "res", "fonts")
LANG_DIR = os.path.join(PROJECT_ROOT, "res", "lang")

SRC_OTF = os.path.join(FONT_DIR, "NotoSansCJK-Subset.otf")
DST_TTF = os.path.join(FONT_DIR, "NotoSansCJK-Subset.ttf")


def get_needed_codepoints():
    """Collect all unique codepoints from CJK translation files."""
    codepoints = set()
    for lang_file in glob.glob(os.path.join(LANG_DIR, "*.json")):
        with open(lang_file, "r", encoding="utf-8") as f:
            data = json.load(f)
        for value in data.values():
            if isinstance(value, str):
                for ch in value:
                    cp = ord(ch)
                    # Include CJK + Hangul + fullwidth + CJK symbols/kana
                    if cp >= 0x2E80:
                        codepoints.add(cp)
    return codepoints


def convert_cff_to_ttf():
    """Convert existing OTF/CFF font to TTF using fontTools cu2qu."""
    from fontTools.ttLib import TTFont
    from fontTools.pens.cu2quPen import Cu2QuPen
    from fontTools.pens.ttGlyphPen import TTGlyphPen

    print(f"Loading {SRC_OTF}...")
    font = TTFont(SRC_OTF)

    # Verify it's CFF
    if "CFF " not in font:
        print("Font is not CFF, skipping conversion")
        return False

    cff = font["CFF "]
    top = cff.cff.topDictIndex[0]
    print(f"ROS: {getattr(top, 'ROS', None)}")
    print(f"CID-keyed: {getattr(top, 'FDSelect', None) is not None}")

    glyphOrder = font.getGlyphOrder()
    print(f"Glyphs: {len(glyphOrder)}")

    # Use fontTools' built-in otf2ttf if available
    try:
        from fontTools.otf2ttf import otf_to_ttf
        otf_to_ttf(font)
        font.save(DST_TTF)
        print(f"Saved TTF: {DST_TTF} ({os.path.getsize(DST_TTF)} bytes)")
        font.close()
        return True
    except ImportError:
        pass

    # Manual conversion using cu2qu
    print("Using manual CFF->TTF conversion with cu2qu...")

    from fontTools.pens.recordingPen import RecordingPen
    from fontTools.pens.pointPen import SegmentToPointPen
    from fontTools import ttLib
    from fontTools.ttLib.tables._g_l_y_f import Glyph as TTGlyph
    import struct

    # Get glyph set
    glyphSet = font.getGlyphSet()

    # Create new glyf table
    from fontTools.ttLib import newTable

    glyf_table = newTable("glyf")
    glyf_table.glyphs = {}
    glyf_table.glyphOrder = glyphOrder

    loca_table = newTable("loca")

    max_error = 1.0  # em-units tolerance for cubic->quadratic

    for gname in glyphOrder:
        try:
            ttPen = TTGlyphPen(glyphSet)
            cu2quPen = Cu2QuPen(ttPen, max_err=max_error, reverse_direction=True)
            glyphSet[gname].draw(cu2quPen)
            glyf_table.glyphs[gname] = ttPen.glyph()
        except Exception as e:
            # Fallback: empty glyph
            glyf_table.glyphs[gname] = TTGlyph()

    # Replace CFF with glyf
    del font["CFF "]
    if "VORG" in font:
        del font["VORG"]

    font["glyf"] = glyf_table
    font["loca"] = loca_table

    # Add required tables for TTF
    # head table needs indexToLocFormat
    font["head"].indexToLocFormat = 1  # long format

    # Create maxp for TrueType
    if "maxp" in font:
        font["maxp"].version = 0x00010000

    # Update sfntVersion
    font.sfntVersion = "\x00\x01\x00\x00"  # TrueType

    font.save(DST_TTF)
    print(f"Saved TTF: {DST_TTF} ({os.path.getsize(DST_TTF)} bytes)")
    font.close()
    return True


def download_and_subset():
    """Download NotoSansSC-Regular.ttf and subset it."""
    import urllib.request
    from fontTools.ttLib import TTFont
    from fontTools import subset

    # Google Fonts provides static TTF files
    url = "https://github.com/notofonts/noto-cjk/raw/main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf"
    # Actually, we want TTF. Let's try the variable font approach.
    # Or better: use google-fonts API for static TTF

    # NotoSansSC static TTF from Google Fonts CDN
    tmp_font = "/tmp/NotoSansSC-Regular.ttf"

    if not os.path.exists(tmp_font):
        print(f"Downloading NotoSansSC-Regular.ttf...")
        url = "https://github.com/notofonts/noto-cjk/raw/main/Sans/OTC/NotoSansCJK-Regular.ttc"
        # This is a TTC (font collection), too large.
        # Use the OTF we already have and convert it.
        return False

    print(f"Using {tmp_font}")
    font = TTFont(tmp_font)
    cmap = font.getBestCmap()
    print(f"Source has {len(cmap)} cmap entries")

    needed = get_needed_codepoints()
    print(f"Need {len(needed)} CJK codepoints")

    # Subset
    subsetter = subset.Subsetter()
    subsetter.populate(unicodes=needed)
    subsetter.subset(font)

    font.save(DST_TTF)
    print(f"Saved: {DST_TTF} ({os.path.getsize(DST_TTF)} bytes)")
    font.close()
    return True


def verify_result():
    """Verify the output TTF has glyf outlines and correct characters."""
    from fontTools.ttLib import TTFont

    font = TTFont(DST_TTF)
    cmap = font.getBestCmap()

    print(f"\n--- Verification ---")
    print(f"Format: {font.sfntVersion!r}")
    print(f"Has glyf: {'glyf' in font}")
    print(f"Has CFF:  {'CFF ' in font}")
    print(f"Cmap entries: {len(cmap)}")

    # Check key characters
    test_chars = {
        "历": 0x5386, "史": 0x53F2,  # Chinese: history
        "概": 0x6982, "述": 0x8FF0,  # Chinese: overview
        "设": 0x8BBE, "置": 0x7F6E,  # Chinese: settings
    }
    for name, cp in test_chars.items():
        status = "YES" if cp in cmap else "NO"
        print(f"  {name} (U+{cp:04X}): {status}")

    size = os.path.getsize(DST_TTF)
    print(f"File size: {size} bytes ({size/1024:.1f} KB)")
    font.close()


if __name__ == "__main__":
    print("=== CJK Font CFF -> TTF Converter ===\n")

    if convert_cff_to_ttf():
        verify_result()
    else:
        print("Direct conversion failed, trying download approach...")
        if download_and_subset():
            verify_result()
        else:
            print("ERROR: Could not convert font")
            sys.exit(1)
