from pathlib import Path
import sys,re,json,uuid,shutil
R=Path(__file__).resolve().parent;B=R.parent;D=R/'cad';D.mkdir(exist_ok=True)
sys.path.insert(0,str(R));from sexpr_forms import forms
source=(R/'sources/template_control.kicad_sch').read_text();lib=next(forms(source,'lib_symbols'))[2]
def uid():return str(uuid.uuid4())
parts=[q for a,z,q in forms(lib,'symbol') if any(q.startswith('(symbol "Project:'+n+'"') for n in ['RES','CAP','CONN5'])]
assert len(parts)==3
pins=[]
for number,x,y,angle in [('1',-5.08,2.54,0),('2',-5.08,-2.54,0),('3',5.08,2.54,180),('4',5.08,-2.54,180)]:
 pins.append('(pin passive line (at %s %s %s) (length 2.54) (name "%s" (effects (font (size 1 1)))) (number "%s" (effects (font (size 1 1)))))'%(x,y,angle,number,number))
parts.append('(symbol "Project:SW4" (pin_names (offset 0.8)) (in_bom yes) (on_board yes) (property "Reference" "SW" (at 0 6.35 0) (effects (font (size 1 1)))) (property "Value" "SW4" (at 0 -6.35 0) (effects (font (size 1 1)))) (symbol "SW4_0_1" (polyline (pts (xy -2.54 2.54) (xy 2.54 2.54)) (stroke (width 0.254) (type default)) (fill (type none))) (polyline (pts (xy -2.54 -2.54) (xy 2.54 -2.54)) (stroke (width 0.254) (type default)) (fill (type none))) (polyline (pts (xy 0 2.54) (xy 1.5 -1.27)) (stroke (width 0.254) (type default)) (fill (type none)))) (symbol "SW4_1_1" '+' '.join(pins)+'))')
sheet=uid();stem='vacuum_panel_a107';instance={};pieces=[]
components=[('J1','CONN5','CTRL PANEL 3V3','Vacuum_Panel:PinHeader_1x05_Drill1.2',40.64,60.96),('SW1','SW4','POWER','Vacuum_Panel:WE430182043816',91.44,50.8),('SW2','SW4','PLUS','Vacuum_Panel:WE430182043816',132.08,50.8),('SW3','SW4','MINUS','Vacuum_Panel:WE430182043816',172.72,50.8),('R1','RES','10k 1%','Resistor_SMD:R_0603_1608Metric',60.96,111.76),('R2','RES','10k 1%','Resistor_SMD:R_0603_1608Metric',132.08,101.6),('R3','RES','22k 1%','Resistor_SMD:R_0603_1608Metric',172.72,101.6),('C1','CAP','10n C0G','Capacitor_SMD:C_0603_1608Metric',91.44,111.76)]
labels={'J1':{'1':'CTRL_3V3','2':'GND','3':'KEY_IN','4':'USER_ADC','5':None},'SW1':{'1':'KEY_IN','3':'KEY_IN','2':'GND','4':'GND'},'SW2':{'1':'USER_ADC','3':'USER_ADC','2':'PLUS_R','4':'PLUS_R'},'SW3':{'1':'USER_ADC','3':'USER_ADC','2':'MINUS_R','4':'MINUS_R'},'R1':{'1':'CTRL_3V3','2':'USER_ADC'},'R2':{'1':'PLUS_R','2':'GND'},'R3':{'1':'MINUS_R','2':'GND'},'C1':{'1':'USER_ADC','2':'GND'}}
for ref,typ,val,fp,x,y in components:
 instance[ref]=uid();datasheet='https://www.we-online.com/components/products/datasheet/430182043816.pdf' if typ=='SW4' else ''
 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,-12.7),('Value',val,-10.16),('Footprint',fp,0),('Datasheet',datasheet,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,instance[ref],props,stem,sheet,ref))
 block=next(q for q in parts if q.startswith('(symbol "Project:'+typ+'"'))
 for a,z,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,uid()))
  else:pieces.append('(label "%s" (at %.2f %.2f 0) (effects (font (size 1 1)) (justify left bottom)) (uuid "%s"))'%(net,px,py,uid()))
text='(kicad_sch (version 20250114) (generator "eeschema") (uuid "%s") (paper "A4") (lib_symbols %s) %s)'%(sheet,' '.join(parts),' '.join(pieces))
(D/(stem+'.kicad_sch')).write_text(text+'\n')
libtext=' '.join(parts).replace('"Project:','"');(D/'Project.kicad_sym').write_text('(kicad_symbol_lib (version 20241209) (generator "kicad_symbol_editor") '+libtext+')\n')
(D/'sym-lib-table').write_text('(sym_lib_table (version 7) (lib (name "Project") (type "KiCad") (uri "${KIPRJMOD}/Project.kicad_sym") (options "") (descr "Panel exact symbols")))\n')
(D/'fp-lib-table').write_text('(fp_lib_table (version 7) (lib (name "Vacuum_Panel") (type "KiCad") (uri "${KIPRJMOD}/Vacuum_Panel.pretty") (options "") (descr "Panel custom geometry")))\n')
shutil.copy2(R/'sources/template_project.kicad_pro',D/(stem+'.kicad_pro'))
pretty=D/'Vacuum_Panel.pretty';pretty.mkdir(exist_ok=True)
standard=Path('/Applications/KiCad/KiCad.app/Contents/SharedSupport/footprints/Connector_PinHeader_2.54mm.pretty/PinHeader_1x05_P2.54mm_Vertical.kicad_mod').read_text().replace('(footprint "PinHeader_1x05_P2.54mm_Vertical"','(footprint "PinHeader_1x05_Drill1.2"').replace('(drill 1)','(drill 1.2)')
(pretty/'PinHeader_1x05_Drill1.2.kicad_mod').write_text(standard)
pads=' '.join('(pad "%s" smd rect (at %s %s) (size 1.55 1.3) (layers "F.Cu" "F.Paste" "F.Mask"))'%(n,x,y) for n,x,y in [('1',-3.975,-2.25),('2',-3.975,2.25),('3',3.975,-2.25),('4',3.975,2.25)])
(pretty/'WE430182043816.kicad_mod').write_text('(footprint "WE430182043816" (version 20241229) (generator "pcbnew") (layer "F.Cu") (attr smd) (property "Reference" "SW" (at 0 -5 0) (layer "F.SilkS") (effects (font (size 1 1)) (justify left))) (property "Value" "430182043816" (at 0 5 0) (layer "F.Fab") (effects (font (size 1 1)))) (fp_rect (start -3.1 -3.1) (end 3.1 3.1) (stroke (width .12) (type default)) (fill none) (layer "F.SilkS")) (fp_rect (start -5 -3.5) (end 5 3.5) (stroke (width .05) (type default)) (fill none) (layer "F.CrtYd")) '+pads+')\n')
(R/'components.json').write_text(json.dumps({'sheet_uuid':sheet,'instance':instance,'components':components,'pin_nets':labels},indent=2)+'\n')
print('panel schematic and footprints generated')
