from pathlib import Path
import re,json,uuid,shutil,sys
R=Path(__file__).resolve().parent;D=R/'cad';D.mkdir(exist_ok=True)
sys.path.insert(0,str(R));from sexpr_forms import forms
lib=next(forms((R/'sources/template_control.kicad_sch').read_text(),'lib_symbols'))[2]
parts=[q for _,_,q in forms(lib,'symbol') if any(q.startswith('(symbol "Project:'+n+'"') for n in ['CAP','CONN5'])];assert len(parts)==2
conn=next(q for q in parts if q.startswith('(symbol "Project:CONN5"'))
for a,z,q in reversed(list(forms(conn,'pin'))):
 if re.search(r'\(number\s+"5"',q):conn=conn[:a]+conn[z:]
parts=[q for q in parts if not q.startswith('(symbol "Project:CONN5"')]+[conn.replace('CONN5','CONN4')]
plist=[]
for num,name,x,y,ang,typ in [('1','NC',-7.62,7.62,0,'no_connect'),('2','VDD',-7.62,2.54,0,'power_in'),('3','NC',-7.62,-2.54,0,'no_connect'),('4','NC',-7.62,-7.62,0,'no_connect'),('8','GND',7.62,7.62,180,'power_in'),('7','SCL',7.62,2.54,180,'input'),('6','SDA',7.62,-2.54,180,'bidirectional'),('5','NC',7.62,-7.62,180,'no_connect')]:
 plist.append('(pin %s line (at %s %s %s) (length 2.54) (name "%s" (effects (font (size 1 1)))) (number "%s" (effects (font (size 1 1)))))'%(typ,x,y,ang,name,num))
parts.append('(symbol "Project:XGZP6897D_C" (pin_names (offset 0.8)) (in_bom yes) (on_board yes) (property "Reference" "U" (at 0 12.7 0) (effects (font (size 1 1)))) (property "Value" "XGZP6897D_C" (at 0 -12.7 0) (effects (font (size 1 1)))) (symbol "XGZP6897D_C_0_1" (rectangle (start -5.08 10.16) (end 5.08 -10.16) (stroke (width .254) (type default)) (fill (type background)))) (symbol "XGZP6897D_C_1_1" '+' '.join(plist)+'))')
sheet=str(uuid.uuid4());stem='vacuum_pressure_a114';info={};pieces=[]
parts0=[('J1','CONN4','A111 J5 3V3/GND/SCL/SDA','Pressure_Adapter:Header_1x04_Drill1.2',40.64,60.96),('U1','XGZP6897D_C','XGZP6897D C ADDR58 RANGE TBD','Pressure_Adapter:XGZP6897D_candidate',91.44,60.96),('C1','CAP','100n 16V X7R','Capacitor_SMD:C_0603_1608Metric',132.08,60.96)]
labels={'J1':{'1':'CTRL_3V3','2':'GND','3':'PANEL_SCL','4':'PANEL_SDA'},'U1':{'1':None,'2':'CTRL_3V3','3':None,'4':None,'5':None,'6':'PANEL_SDA','7':'PANEL_SCL','8':'GND'},'C1':{'1':'CTRL_3V3','2':'GND'}}
url='https://cfsensor.com/wp-content/uploads/2026/09/XGZP6897D-Pressure-Sensor-V3.3.pdf'
for ref,typ,val,fp,x,y in parts0:
 uid=str(uuid.uuid4());info[ref]=uid
 props=' '.join('(property '+json.dumps(k)+' '+json.dumps(v)+' (at %.2f %.2f 0) (effects (font (size 1 1))%s))'%(x,y+off,' (hide yes)' if k in ['Footprint','Datasheet'] else '') for k,v,off in [('Reference',ref,-17.78),('Value',val,-15.24),('Footprint',fp,0),('Datasheet',url if ref=='U1' else '',0)])
 pieces.append('(symbol (lib_id "Project:%s") (at %.2f %.2f 0) (unit 1) (in_bom yes) (on_board yes) (dnp no) (uuid "%s") %s (instances (project "%s" (path "/%s" (reference "%s") (unit 1)))))'%(typ,x,y,uid,props,stem,sheet,ref))
 block=next(q for q in parts if q.startswith('(symbol "Project:'+typ+'"'))
 for _,_,pin in forms(block,'pin'):
  number=re.search(r'\(number\s+"([^\"]+)"',pin)[1];pos=re.search(r'\(at\s+([^\)]+)',pin)[1].split();px=x+float(pos[0]);py=y-float(pos[1]);net=labels[ref][number]
  if net is None:pieces.append('(no_connect (at %.2f %.2f) (uuid "%s"))'%(px,py,uuid.uuid4()))
  else:pieces.append('(label "%s" (at %.2f %.2f 0) (effects (font (size 1 1)) (justify left bottom)) (uuid "%s"))'%(net,px,py,uuid.uuid4()))
parts.append('(symbol "Project:PWR_FLAG" (power) (pin_names (offset 0) (hide yes)) (in_bom no) (on_board no) (property "Reference" "#FLG" (at 0 1.27 0) (effects (font (size 1 1)) (hide yes))) (property "Value" "PWR_FLAG" (at 0 3.81 0) (effects (font (size 1 1)))) (symbol "PWR_FLAG_0_1" (polyline (pts (xy 0 0) (xy 0 1.27) (xy 1.27 1.27) (xy 0 2.54) (xy -1.27 1.27) (xy 0 1.27)) (stroke (width .15) (type default)) (fill (type none)))) (symbol "PWR_FLAG_1_1" (pin power_out line (at 0 0 90) (length 0) (name "pwr" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))))')
for i,net in enumerate(['CTRL_3V3','GND']):
 x=40.64+i*25.4;y=101.6;uid=str(uuid.uuid4());ref='#FLG'+str(i+1)
 pieces.append('(symbol (lib_id "Project:PWR_FLAG") (at %.2f %.2f 0) (unit 1) (in_bom no) (on_board no) (dnp no) (uuid "%s") (property "Reference" "%s" (at %.2f %.2f 0) (effects (font (size 1 1)) (hide yes))) (property "Value" "PWR_FLAG" (at %.2f %.2f 0) (effects (font (size 1 1)))) (instances (project "%s" (path "/%s" (reference "%s") (unit 1)))))'%(x,y,uid,ref,x,y,x,y-5.08,stem,sheet,ref))
 pieces.append('(label "%s" (at %.2f %.2f 0) (effects (font (size 1 1)) (justify left bottom)) (uuid "%s"))'%(net,x,y,uuid.uuid4()))
(D/(stem+'.kicad_sch')).write_text('(kicad_sch (version 20250114) (generator "eeschema") (uuid "%s") (paper "A4") (lib_symbols %s) %s)\n'%(sheet,' '.join(parts),' '.join(pieces)))
(D/'Project.kicad_sym').write_text('(kicad_symbol_lib (version 20241209) (generator "kicad_symbol_editor") '+' '.join(parts).replace('"Project:','"')+')\n')
(D/'sym-lib-table').write_text('(sym_lib_table (version 7) (lib (name "Project") (type "KiCad") (uri "${KIPRJMOD}/Project.kicad_sym") (options "") (descr "Pressure adapter candidate")))\n')
(D/'fp-lib-table').write_text('(fp_lib_table (version 7) (lib (name "Pressure_Adapter") (type "KiCad") (uri "${KIPRJMOD}/Pressure_Adapter.pretty") (options "") (descr "Manufacturer drawing candidate")))\n')
shutil.copy2(R/'sources/template_project.kicad_pro',D/(stem+'.kicad_pro'))
pretty=D/'Pressure_Adapter.pretty';pretty.mkdir(exist_ok=True)
standard=Path('/Applications/KiCad/KiCad.app/Contents/SharedSupport/footprints/Connector_PinHeader_2.54mm.pretty/PinHeader_1x04_P2.54mm_Vertical.kicad_mod').read_text().replace('(footprint "PinHeader_1x04_P2.54mm_Vertical"','(footprint "Header_1x04_Drill1.2"').replace('(drill 1)','(drill 1.2)');(pretty/'Header_1x04_Drill1.2.kicad_mod').write_text(standard)
pads=[]
for num,x,y in [('1',-4.98,-3.81),('2',-4.98,-1.27),('3',-4.98,1.27),('4',-4.98,3.81),('5',4.98,3.81),('6',4.98,1.27),('7',4.98,-1.27),('8',4.98,-3.81)]:
 pads.append('(pad "%s" smd rect (at %s %s) (size 2 .9) (layers "F.Cu" "F.Paste" "F.Mask"))'%(num,x,y))
(pretty/'XGZP6897D_candidate.kicad_mod').write_text('(footprint "XGZP6897D_candidate" (version 20241229) (generator "pcbnew") (layer "F.Cu") (descr "Candidate land derived from V3.3 p3, rotated top view clockwise90deg; manufacturer approval pending") (attr smd) (property "Reference" "U" (at 0 -7 0) (layer "F.SilkS") (effects (font (size 1 1)))) (property "Value" "XGZP6897D" (at 0 7 0) (layer "F.Fab") (effects (font (size 1 1)))) (fp_rect (start -3.5 -5.5) (end 3.5 5.5) (stroke (width .12) (type default)) (fill none) (layer "F.SilkS")) (fp_rect (start -6.25 -6.25) (end 6.25 6.25) (stroke (width .05) (type default)) (fill none) (layer "F.CrtYd")) (fp_circle (center -3 -4.8) (end -2.7 -4.8) (stroke (width .12) (type default)) (fill none) (layer "F.SilkS")) '+' '.join(pads)+')\n')
(R/'components.json').write_text(json.dumps({'sheet_uuid':sheet,'instance':info,'components':parts0,'pin_nets':labels},indent=2))
print('generated native schematic + candidate footprint')
