import {driver,type Driver,type DriveStep} from 'driver.js'; const GUIDE_KEY='behind-glass.first-guide.v1',RECENTER_KEY='behind-glass.recenter-guide.v1'; /** A nonmodal marker preserves the app's existing blocking/cancellation contract. * Driver owns the visible spotlight; underlying app stays inert, never auto-clicked. */ export function initFirstGuide(root:Document,signal:AbortSignal,mobile:boolean,eligible:()=>boolean,onChange:()=>void,createTour:typeof driver=driver){ const get=(id:string)=>root.querySelector(`#${id}`)!; const marker=get('first-guide'),app=get('experience'),view=root.defaultView; let done=false,recenterDone=false,tour:Driver|null=null,active=false,ending=false,priorInert=false,kind:'main'|'recenter'='main'; try{done=view?.localStorage.getItem(GUIDE_KEY)==='1';recenterDone=view?.localStorage.getItem(RECENTER_KEY)==='1';}catch{/* session-only state */} const visible=(id:string):HTMLElement|undefined=>{const node=root.querySelector(`#${id}`);if(!node||node.closest('[hidden]'))return;const r=node.getBoundingClientRect(),style=view?.getComputedStyle?.(node);return r.width>0&&r.height>0&&style?.visibility!=='hidden'&&style?.display!=='none'?node:undefined;}; const cleanup=()=>{if(!active)return;active=false;tour=null;app.inert=priorInert;if(marker.open)marker.close();onChange();}; const stop=(completed=false)=>{ if(!active&&!tour)return; ending=true; if(completed){if(kind==='main')done=true;else recenterDone=true;try{view?.localStorage.setItem(kind==='main'?GUIDE_KEY:RECENTER_KEY,'1');}catch{/* keep session state */}} const current=tour;tour=null; try{current?.destroy();}finally{cleanup();ending=false;onChange();} }; const start=(steps:DriveStep[],type:'main'|'recenter')=>{ if(signal.aborted||active||ending||!eligible())return; kind=type;priorInert=app.inert;active=true;marker.show();app.inert=true;onChange(); try{ tour=createTour({steps,animate:!view?.matchMedia?.('(prefers-reduced-motion: reduce)').matches,overlayColor:'#201a13',overlayOpacity:.62,stagePadding:9,stageRadius:9,popoverOffset:12, allowScroll:false,smoothScroll:false,disableActiveInteraction:true,skipMissingElement:true,overlayClickBehavior:'none',allowClose:true,showProgress:type==='main',progressText:'{{current}} / {{total}}', nextBtnText:'다음',prevBtnText:'이전',doneBtnText:type==='main'?'시작하기':'알겠어요',closeBtnLabel:'안내 건너뛰기',popoverClass:'behind-glass-tour', onNextClick:()=>{if(tour?.isLastStep())stop(true);else tour?.moveNext();},onDoneClick:()=>stop(true),onCloseClick:()=>stop(true),onDestroyStarted:()=>stop(true),onDestroyed:cleanup, onPopoverRender:popover=>{popover.closeButton.textContent='건너뛰기';const content=root.createElement('div');content.className='guide-popover-content';content.append(popover.closeButton,popover.title,popover.description,popover.footer);popover.wrapper.append(content);}, }); tour.drive(); }catch{stop(false);} }; marker.addEventListener('close',()=>{if(!marker.open)stop(false);},{signal}); marker.addEventListener('cancel',event=>{event.preventDefault();stop(true);},{signal}); const refresh=()=>{if(!active)return;const target=tour?.getActiveElement?.();if(target&&target.id&&!visible(target.id)){stop(false);return;}tour?.refresh();}; view?.visualViewport?.addEventListener('resize',refresh,{signal});view?.visualViewport?.addEventListener('scroll',refresh,{signal}); signal.addEventListener('abort',()=>stop(false),{once:true}); return { start(force=false){ if((done&&!force)||signal.aborted)return; const steps:DriveStep[]=[ {element:()=>visible('guide-scene-target')!,popover:{title:'유리 너머를 둘러보세요',description:mobile?'손가락으로 드래그해서 시점을 바꾸고, 두 손가락으로 확대해 보세요.':'드래그해서 시점을 바꾸고, 마우스 휠로 확대해 보세요.',side:'bottom',align:'center'}}, {element:()=>visible('door-toggle')!,popover:{title:'문도 열어볼까요?',description:'이 버튼으로 문을 열고 닫을 수 있어요. 문 손잡이를 좌우로 밀어도 돼요.',side:'top',align:'start'}}, ...(mobile?[{element:()=>visible('gyro')!,popover:{title:'휴대폰을 기울여 보세요',description:'안내를 마친 뒤 이 버튼을 눌러 연결해 주세요. 기울기를 쓰지 않아도 드래그로 둘러볼 수 있어요.',side:'bottom' as const,align:'end' as const}}]:[]), ]; start(steps,'main'); }, recenter(){if(!mobile||!done||recenterDone||!visible('gyro-recenter'))return;start([{element:()=>visible('gyro-recenter')!,popover:{title:'편한 자세로 중앙 맞추기',description:'휴대폰을 편하게 든 뒤 이 버튼을 누르면 지금 자세가 새로운 기준이 돼요. 확대 정도는 그대로 유지돼요.',side:'top',align:'end'}}],'recenter');}, }; }