"""ASX: one captive lid clamp, documented internals and folding heel blocks."""

def build_service(shell,base,seam):
    for ob in (shell,base,seam):
        cut(ob,cube('Service / internal clearance',(0,0,1.02),(35.9,23.6,2.5),None,.43))
    inside=group('service_internals')
    parent(cube('Service / structural spine',(0,0,2.24),(35.7,23.4,.13),ALUMINUM,.37),inside)
    parent(cube('Service / system board',(0,0,2.11),(32.9,20.5,.10),PCB,.20),inside)
    diagram=group('Service / internal silkscreen');parent(diagram,inside);diagram.rotation_euler.x=math.pi;diagram.location.z=2.044
    def label(body,x,y,size=.23,mat=WHITE,bold=False):
        return parent(text('Service / '+body,body,(x,y,.014),size,mat,bold=bold),diagram)
    def line(pts,mat=WHITE):
        stroke(diagram,'Service / printed rule',[(x,y,.012) for x,y in pts],mat,.017)
    label('ASX / SERVICE ARCHITECTURE',-15,9.18,.39,bold=True)
    label('MEMORY A',3.2,8.3,.24);label('MEMORY B',3.2,3.1,.24)
    outline=[(-5,-1.45),(-1.2,-1.45),(-.7,-1.93),(1.3,-1.93),(1.8,-1.45),(5,-1.45),(5,1.45),(1.8,1.45),(1.3,1.93),(-.7,1.93),(-1.2,1.45),(-5,1.45)]
    for i,cy in enumerate((-6.05,-.88)):
        cx=8.6;mount=group('memory_'+('a' if i==0 else 'b'));parent(mount,inside)
        parent(cube('Memory / compression connector',(cx,cy,1.97),(7.9,2.52,.22),BLACK,.11),mount)
        parent(prism('Memory / LPCAMM2 stepped board',[(cx+x,cy+y) for x,y in outline],1.70,1.82,BASE,.025),mount)
        for dx in (-3.31,-1.10,1.10,3.31):
            parent(cube('Memory / LPDDR5X package',(cx+dx,cy,1.58),(1.70,1.76,.22),BLACK,.06),mount)
            parent(text('Memory / chip mark','LPDDR5X',(cx+dx,cy,1.459),.16,WHITE,rotation=(math.pi,0,0),align='CENTER'),mount)
        for j,(dx,dy) in enumerate(((-4.7,-1.12),(0,1.58),(4.7,-1.12))):
            fast=group('Memory / fastener');parent(fast,mount);fast.location=(cx+dx,cy+dy,1.63);fast.rotation_euler.x=math.pi
            parent(cyl('Memory / captive screw',(0,0,0),.14,.09,ALUMINUM,32),fast)
            parent(cyl('Memory / driver recess',(0,0,.053),.058,.006,BLACK,6,bevel=0),fast)
            parent(text('Memory / screw index',str(j+1),(cx+dx-.3,cy+dy,1.629),.17,WHITE,rotation=(math.pi,0,0)),mount)
    parent(cube('SYS / NVMe board',(-9.30,-4.20,1.87),(8.0,2.25,.15),PCB,.07),inside)
    for x in (-11.8,-9.3,-6.8):parent(cube('SYS / NAND package',(x,-4.2,1.70),(1.73,1.68,.24),BLACK,.08),inside)
    label('SYS / NVMe SYSTEM STORAGE',-13.6,6.07,.26,bold=True)
    label('01 RELEASE     02 SLIDE',-13.6,2.25,.21)
    line([(-13.6,2.61),(-5.0,2.61)])
    parent(cube('Thermal / chamber',(-7.9,2.2,1.87),(12.1,4.5,.33),ALUMINUM,.36),inside)
    for cx in (-11.7,-4.25):
        parent(cyl('Thermal / blower housing',(cx,7.35,1.65),3.22,.45,BLACK,64),inside)
        parent(cyl('Thermal / blower hub',(cx,7.35,1.34),.85,.23,ALUMINUM,48),inside)
        for i in range(23):
            a=i*2*math.pi/23
            parent(cube('Thermal / swept fan blade',(cx+1.94*math.cos(a),7.35+1.94*math.sin(a),1.34),(1.93,.19,.24),GRAPHITE,.04,rot=(0,0,a+.42)),inside)
    label('AIR / FILTER + FAN ACCESS',-14.8,-10.25,.24,bold=True)
    parent(cube('Service / radio module',(6.0,7.25,1.91),(3.15,4.30,.16),PCB,.07),inside)
    parent(cube('Service / RF shield',(6,7.5,1.72),(2.80,2.7,.22),ALUMINUM,.10),inside)
    parent(cyl('Service / RTC cell',(11.90,7.25,1.71),1.0,.32,ALUMINUM,48),inside)
    parent(cube('service_recovery',(14.45,7.15,1.70),(.69,.69,.34),ORANGE,.12),inside)
    label('RADIO',4.5,-4.5,.22);label('CLOCK',10.9,-4.5,.22);label('RECOVERY',13.3,-4.5,.18)
    label('USER SERVICE ACCESS',3.8,-10.20,.30,bold=True)
    for cx,cy in ((-15,0),(1.5,8.5),(1.5,-9.5)):
        parent(cube('Service / cable header',(cx,cy,1.92),(1.15,.55,.32),CREAM,.06),inside)
        for k in range(4):
            stroke(inside,'Service / harness',[(cx-.34+k*.20,cy,1.73),(cx-.34+k*.20,cy+1.3,1.73),(cx+1.1,cy+1.7+k*.2,1.73)],ORANGE if k==0 else BLACK,.074)
    # The flat service assembly must clear the lowest point of the sloping deck.
    electronics=group('service_electronics');parent(electronics,inside)
    for ob in list(inside.children):
        if ob!=electronics:parent(ob,electronics)
    electronics.location.z=-.52
    lid=group('service_lid');lid.location.z=.16;lid.rotation_euler.x=math.pi
    plate=parent(cube('Service / complete lid',(0,0,0),(35.65,23.15,.22),BASE,.38),lid)
    for x in (-15.7,15.7):
        for y in (-9.48,10.05):
            cut(plate,parent(cube('Service / heel relief',(x,y,0),(4.05,4.42,1),None,.32),lid))
    def silk(body,x,y,size=.25,mat=WHITE,bold=False):
        return parent(text('Lid / '+body,body,(x,y,.122),size,mat,bold=bold),lid)
    def rule(points,mat=WHITE,width=.018):
        stroke(lid,'Lid / silkscreen',[(x,y,.123) for x,y in points],mat,width)
    silk('ASX',-14.65,6.74,2.65,bold=True)
    silk('ArtiSan eXtended',-14.48,4.83,.47)
    rule([(-14.50,4.20),(-3.68,4.20)],width=.036)
    silk('ARTISAN / ALTO / AT-101',-14.48,3.57,.32,bold=True)
    silk('PERSONAL COMPUTER SYSTEM',-14.48,2.95,.22)
    silk('ARCHITECTURE 08 / SERVICE EDITION',-14.48,2.42,.18)
    for i,cy in enumerate((6.1,.98)):
        rule([(8.6+x,cy+y) for x,y in outline+[outline[0]]])
        silk('MEMORY '+('A' if i==0 else 'B'),3.86,cy+.75,.32,bold=True)
        silk('LPCAMM2 / COMPRESSION ATTACHED',3.86,cy+.16,.20)
        silk('LOW POWER / FIELD REPLACEABLE',3.86,cy-.40,.17,MOD)
        for dx,dy in ((-4.7,-1.12),(0,1.58),(4.7,-1.12)):
            rule([(8.6+dx+.13*math.cos(j*math.pi/8),cy+dy+.13*math.sin(j*math.pi/8)) for j in range(17)],width=.013)
    silk('MEM',3.6,9.43,.95,bold=True)
    silk('TWO MEMORY POSITIONS',7.14,9.40,.22)
    for i in range(29):
        cut(plate,parent(cube('Service / intake cut',(-13.7+i*.405,-3.0,0),(.19,4.05,1),None,.055),lid))
    silk('AIR',-14.3,-.23,.74,bold=True)
    silk('REMOVABLE FILTER / KEEP CLEAR',-11.96,-.26,.20)
    silk('SYS / INTERNAL NVMe',3.5,-2.20,.26,bold=True)
    silk('RADIO / CLOCK / RECOVERY',3.5,-2.76,.22)
    rule([(3.5,-3.20),(13.4,-3.20)])
    silk('USER SERVICE ACCESS',3.5,-3.85,.25,bold=True)
    silk('ONE COVER / COMPLETE ACCESS',3.5,-4.40,.18)
    silk('SINGLE-POINT LID CLAMP',-13.8,-6.50,.43,bold=True)
    rule([(-13.8,-7.01),(7.1,-7.01)],width=.028)
    silk('Unscrew to free, pull to pop case open',-13.8,-7.55,.29)
    silk('01 / UNSCREW     02 / PULL     03 / LIFT',-13.8,-8.23,.21)
    cut(plate,parent(cube('Service / clamp well',(9.38,-7.65,0),(3.62,2.67,1),None,.20),lid))
    clamp=group('lid_clamp');parent(clamp,lid);clamp.location=(9.38,-7.65,-.10)
    parent(cube('Clamp / finger pocket',(0,0,-.07),(3.65,2.78,.15),BLACK,.22),clamp)
    parent(cube('Clamp / body',(0,0,0),(3.26,2.39,.31),GRAPHITE,.23),clamp)
    parent(cube('Clamp / grip',(0,-.81,.15),(2.78,.55,.24),RED_DARK,.12),clamp)
    for i in range(9):parent(cube('Clamp / grip flute',(-1.05+i*.264,-.81,.288),(.074,.36,.044),ORANGE,.014),clamp)
    fast=group('lid_clamp_screw');parent(fast,clamp)
    parent(cyl('Clamp / screw collar',(0,.39,.19),.36,.11,ALUMINUM,48),fast)
    parent(cyl('Clamp / screw head',(0,.39,.261),.255,.05,STEEL,40),fast)
    parent(cyl('Clamp / driver socket',(0,.39,.29),.12,.007,BLACK,6,bevel=0),fast)
    rule([(11.65,-6.56),(11.65,-8.58)],width=.085)
    rule([(11.17,-8.08),(11.65,-8.58),(12.13,-8.08)],width=.085)
    silk('PULL',12.36,-7.45,.22,bold=True)
    inner=group('Lid / inner map');parent(inner,lid);inner.rotation_euler.x=math.pi;inner.location.z=-.122
    parent(text('Lid / internal legend','ASX / COMPONENT MAP',(-13,7,.005),.55,WHITE,bold=True),inner)
    for i,body in enumerate(('01 MEMORY A + B','02 SYSTEM STORAGE','03 AIR / FILTER / FANS','04 RADIO / CLOCK / RECOVERY')):
        parent(text('Lid / component legend',body,(-13,5.6-i*.72,.007),.27,WHITE),inner)
    heels=[]
    for side,x in (('left',-15.7),('right',15.7)):
        parent(cube('Service / fixed heel well',(x,9.55,.59),(3.84,4.29,.38),BLACK,.26),inside)
        heel=group('heel_'+side);heel.location=(x,11.06,.42);heels.append(heel)
        parent(cube('Heel / sculpted block',(0,-1.52,-.08),(3.18,3.24,.44),RED_DARK,.28),heel)
        parent(cube('Heel / replaceable sole',(0,-2.84,-.33),(3.1,.67,.28),BLACK,.17),heel)
        parent(cyl('Heel / pivot',(0,0,-.015),.24,3.28,ALUMINUM,40,rot=(0,math.pi/2,0)),heel)
        for j in range(6):parent(cube('Heel / grip rib',(-1.15+j*.46,-1.76,-.314),(.16,1.21,.08),GRAPHITE,.025),heel)
        parent(text('Heel / tilt legend','0 / 1 / 2',(-.90,-.71,-.326),.22,WHITE,rotation=(math.pi,0,0)),heel)
        parent(text('Heel / tilt caption','THREE-POSITION TILT',(x-1.78,7.02,.31),.17,WHITE,rotation=(math.pi,0,0)),inside)
        parent(cube('Service / front rubber pad',(x,-10.27,.12),(3.40,2.35,.40),BLACK,.35),inside)
    return lid,clamp,heels,inside
