import uuid, re, sys
OUT = sys.argv[1]; PROJECT = "chronotype_typewriter"
ROOT = "7a1c2e5e-0c44-4d4e-9f1a-typewriter0001"
ROOT = "7a1c2e5e-0c44-4d4e-9f1a-000000000001"
FAB = "/Users/fhaddad/Documents/KiCad/10.0/3rdparty/fab/symbols/fab.kicad_sym"
KS = "/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols/"
U = lambda: str(uuid.uuid4())
pinre = re.compile(r'\(pin (\w+) \w+\s*\(at ([-\d.]+) ([-\d.]+) (\d+)\)\s*\(length ([\d.]+)\)\s*(?:\(hide yes\)\s*)?\(name "([^"]*)"\s*\(effects.*?\)\s*\)\s*\(number "([^"]*)"', re.S)
def block(src, name):
    i = src.find(f'(symbol "{name}"'); d = 0; j = i
    while True:
        c = src[j]
        if c == "(": d += 1
        elif c == ")":
            d -= 1
            if d == 0: return src[i:j+1]
        j += 1
SYMS = {}
def load(libfile, libnick, name, fp_override=None):
    src = open(libfile).read(); b = block(src, name)
    fp = re.search(r'\(property "Footprint" "([^"]*)"', b); fp = fp.group(1) if fp else ""
    if fp_override is not None: fp = fp_override
    SYMS[name] = {"lib": libnick, "text": b.replace(f'(symbol "{name}"', f'(symbol "{libnick}:{name}"', 1),
                  "pins": {m.group(7): (float(m.group(2)), float(m.group(3)), int(m.group(4))) for m in pinre.finditer(b)}, "fp": fp}
load(FAB, "PCM_fab", "Module_XIAO-RP2040")
load(FAB, "PCM_fab", "R_1206")
load(FAB, "PCM_fab", "LED_1206")
load(FAB, "PCM_fab", "Switch_Tactile_CnK")
load(KS+"Connector_Generic.kicad_sym", "Connector_Generic", "Conn_01x12", "Connector_JST:JST_XH_B12B-XH-A_1x12_P2.50mm_Vertical")
load(KS+"Connector_Generic.kicad_sym", "Connector_Generic", "Conn_01x04", "PCM_fab:PinSocket_01x04_P2.54mm_Vertical_SMD")
load(KS+"Mechanical.kicad_sym", "Mechanical", "MountingHole", "MountingHole:MountingHole_3.2mm_M3")
load(KS+"power.kicad_sym", "power", "PWR_FLAG")

out = []; wires = []; labels = []; ncs = []
def place(name, ref, value, x, y, ref_off=(2.54,-2.54), val_off=(2.54,0)):
    s = SYMS[name]; pins = s["pins"]
    pin_uuids = "".join(f'\n\t\t(pin "{p}"\n\t\t\t(uuid "{U()}")\n\t\t)' for p in pins)
    out.append(f'''\t(symbol
\t\t(lib_id "{s['lib']}:{name}")
\t\t(at {x} {y} 0)
\t\t(unit 1)
\t\t(exclude_from_sim no)
\t\t(in_bom yes)
\t\t(on_board yes)
\t\t(dnp no)
\t\t(uuid "{U()}")
\t\t(property "Reference" "{ref}"
\t\t\t(at {x+ref_off[0]} {y+ref_off[1]} 0)
\t\t\t(effects (font (size 1.27 1.27)) (justify left))
\t\t)
\t\t(property "Value" "{value}"
\t\t\t(at {x+val_off[0]} {y+val_off[1]} 0)
\t\t\t(effects (font (size 1.27 1.27)) (justify left))
\t\t)
\t\t(property "Footprint" "{s['fp']}"
\t\t\t(at {x} {y} 0)
\t\t\t(effects (font (size 1.27 1.27)) (hide yes))
\t\t)
\t\t(property "Datasheet" ""
\t\t\t(at {x} {y} 0)
\t\t\t(effects (font (size 1.27 1.27)) (hide yes))
\t\t){pin_uuids}
\t\t(instances
\t\t\t(project "{PROJECT}"
\t\t\t\t(path "/{ROOT}"
\t\t\t\t\t(reference "{ref}")
\t\t\t\t\t(unit 1)
\t\t\t\t)
\t\t\t)
\t\t)
\t)''')
    return {p: (round(x+px,2), round(y-py,2), prot) for p,(px,py,prot) in pins.items()}
def stub(pt, net, length=5.08):
    x, y, prot = pt
    dx, dy = {0:(-1,0), 180:(1,0), 90:(0,1), 270:(0,-1)}[prot]
    x2, y2 = round(x+dx*length,2), round(y+dy*length,2)
    wires.append(f'\t(wire\n\t\t(pts\n\t\t\t(xy {x} {y}) (xy {x2} {y2})\n\t\t)\n\t\t(stroke (width 0) (type default))\n\t\t(uuid "{U()}")\n\t)')
    lrot = {0:180, 180:0, 90:270, 270:90}[prot]
    just = {0:"right bottom", 180:"left bottom", 90:"right bottom", 270:"left bottom"}[prot]
    labels.append(f'\t(label "{net}"\n\t\t(at {x2} {y2} {lrot})\n\t\t(effects (font (size 1.27 1.27)) (justify {just}))\n\t\t(uuid "{U()}")\n\t)')
def nc(pt): ncs.append(f'\t(no_connect\n\t\t(at {pt[0]} {pt[1]})\n\t\t(uuid "{U()}")\n\t)')

# XIAO: SO D0, SCK D1, SI D2, READY D3, D4 spare->breakout, PWR_MCU D5, KBACK D6, KBRQ D7, LED D8, SEL D9, D10 spare->breakout
m = place("Module_XIAO-RP2040", "M1", "XIAO RP2040", 63.5, 76.2, ref_off=(-10.16,-19.05), val_off=(-10.16,25.4))
for pin, net in [("1","KBRQ_MCU"),("2","PWR_MCU"),("3","KBACK_MCU"),("4","SO_MCU"),("5","READY_MCU"),("6","SI_MCU"),("7","SCK_MCU"),("8","LED_MCU"),("9","SEL_MCU"),("10","BK_D9"),("11","BK_D10"),("12","3V3")]:
    stub(m[pin], net)
for pin in ["14","16","17","20","18"]: nc(m[pin])
for pin in ["13","15","19"]: stub(m[pin], "GND", 2.54)
# outputs
for i,(a,b) in enumerate([("SCK_MCU","SCK"),("SI_MCU","SI"),("READY_MCU","READY")]):
    r = place("R_1206", f"R{i+1}", "100", 121.92+i*10.16, 48.26); stub(r["1"], a, 2.54); stub(r["2"], b, 2.54)
# dividers: SO (R4/R5), KBACK (R6/R7), KBRQ (R8/R9), PWR (R12/R13)
for i,(bus, mcu, rt, rb) in enumerate([("SO","SO_MCU","R4","R5"),("KBACK","KBACK_MCU","R6","R7"),("KBRQ_J","KBRQ_MCU","R8","R9"),("PWR","PWR_MCU","R12","R13")]):
    x = 121.92+i*12.7; y = 86.36
    a = place("R_1206", rt, "4.99k", x, y); b = place("R_1206", rb, "10k", x, y+15.24)
    stub(a["1"], bus, 2.54)
    wires.append(f'\t(wire\n\t\t(pts\n\t\t\t(xy {a["2"][0]} {a["2"][1]}) (xy {b["1"][0]} {b["1"][1]})\n\t\t)\n\t\t(stroke (width 0) (type default))\n\t\t(uuid "{U()}")\n\t)')
    labels.append(f'\t(label "{mcu}"\n\t\t(at {x} {y+7.62} 0)\n\t\t(effects (font (size 1.27 1.27)) (justify left bottom))\n\t\t(uuid "{U()}")\n\t)')
    stub(b["2"], "GND", 2.54)
r11 = place("R_1206", "R11", "0", 152.4, 48.26); stub(r11["1"], "KBRQ", 2.54); stub(r11["2"], "KBRQ_J", 2.54)
r10 = place("R_1206", "R10", "100", 177.8, 48.26); stub(r10["1"], "LED_MCU", 2.54); stub(r10["2"], "LED_A", 2.54)
d1 = place("LED_1206", "D1", "LED blue", 177.8, 68.58, ref_off=(-2.54,-5.08), val_off=(-2.54,5.08)); stub(d1["2"], "LED_A", 2.54); stub(d1["1"], "GND", 2.54)
sw = place("Switch_Tactile_CnK", "SW1", "SELECT", 177.8, 109.22, ref_off=(-2.54,-5.08), val_off=(-2.54,5.08)); stub(sw["1"], "SEL_MCU", 2.54); stub(sw["2"], "GND", 2.54)
pf = place("PWR_FLAG", "#FLG01", "PWR_FLAG", 63.5, 109.22, ref_off=(2.54,0), val_off=(2.54,2.54)); stub(pf["1"], "GND", 2.54)
pf2 = place("PWR_FLAG", "#FLG02", "PWR_FLAG", 83.82, 109.22, ref_off=(2.54,0), val_off=(2.54,2.54)); stub(pf2["1"], "3V3", 2.54)
# typewriter bus connector: provisional 1:1 with the Brother plug numbering
j = place("Conn_01x12", "J1", "Typewriter 12-pin (JST XH)", 210.82, 73.66, ref_off=(-5.08,-20.32), val_off=(-12.7,22.86))
for pin, net in [("1","GND"),("2","SCK"),("3","SI"),("4","READY"),("5","SO"),("6","KBACK"),("7","PWR"),("8","KBRQ"),("10","GND"),("11","GND")]:
    stub(j[pin], net, 2.54)
for pin in ["9","12"]: nc(j[pin])
j2 = place("Conn_01x04", "J2", "OLED", 210.82, 109.22, ref_off=(-5.08,-7.62), val_off=(-7.62,8.89))
for pin, net in [("1","GND"),("2","3V3"),("3","BK_D10"),("4","BK_D9")]: stub(j2[pin], net, 2.54)
for i in range(4): place("MountingHole", f"H{i+1}", "M3", 30.48+i*12.7, 127.0, ref_off=(-2.54,-5.08), val_off=(-2.54,5.08))

notes = [
 (121.92, 17.78, "Outputs XIAO -> typewriter: SCK (D6), SI (D5), READY (D4) through 100 R. 3.3 V is a valid high for the typewriter's 7407 inputs."),
 (121.92, 21.59, "Inputs typewriter -> XIAO: SO (D3), KBACK (D2), KBRQ (D0), +5 V power sense (D1), each through a 4.99k/10k divider (5 V -> 3.34 V)."),
 (121.92, 25.4, "R11 = 0 R jumper (lets KBRQ cross the ground trace on the single-sided board). LED D7 = ONLINE lamp, SW1 D8 = SELECT (space bar)."),
 (121.92, 127.0, "J1 pin order is PROVISIONAL (chosen for routing): 1 GND  2 SCK  3 SI  4 READY  5 SO  6 KBACK  7 +5V sense  8 KBRQ  9 nc  10-11 GND  12 nc."),
 (121.92, 130.81, "Plug pins 11/12 carry +30 V and are never wired. Re-pin the harness housing to match after the continuity map."),
 (121.92, 134.62, "J2 = OLED socket in the standard 0.96in order GND VDD SCL(D10) SDA(D9): a module plugs in directly, or 4 wires to the case lid."),
 (121.92, 138.43, "ChronoType IF-60 replacement, HTMAA 2026 week 5. Bus spec: Brother CE-650 service manual ch. 9 + LooksLikeThomas/brother-serial-interface-adapter."),
]
texts = "".join(f'\n\t(text "{t}"\n\t\t(exclude_from_sim no)\n\t\t(at {x} {y} 0)\n\t\t(effects (font (size 1.27 1.27)) (justify left bottom))\n\t\t(uuid "{U()}")\n\t)' for x,y,t in notes)
sch = f'''(kicad_sch
\t(version 20260306)
\t(generator "eeschema")
\t(generator_version "10.0")
\t(uuid "{ROOT}")
\t(paper "A4")
\t(title_block
\t\t(title "ChronoType IF-60 replacement (typewriter board)")
\t\t(date "2026-10-13")
\t\t(rev "0.3")
\t\t(company "Fadi G. Haddad, MIT HTMAA 2026")
\t)
\t(lib_symbols
{chr(10).join(s["text"] for s in SYMS.values())}
\t)
{chr(10).join(wires)}
{chr(10).join(labels)}
{chr(10).join(ncs)}
{texts}
{chr(10).join(out)}
\t(sheet_instances
\t\t(path "/"
\t\t\t(page "1")
\t\t)
\t)
\t(embedded_fonts no)
)
'''
open(OUT, "w").write(sch); print("schematic written:", len(out), "symbols")
