import { ThreeDViewer } from './viewer/ThreeDViewer';
import { initDropzone } from './dnd/dropzone';
import { setStatus } from './ui/progress';
import { publicAssetUrl } from './runtimeBase';

/**
 * Entry point. Wires the ThreeDViewer (renderer + loaders + hydration) and the
 * Drag & Drop local-file path. Path A (server asset) is also available via the
 * `?model=<url>` query param so the SSR+CSR+hydration flow can be exercised
 * without extra UI.
 */
const viewerEl = document.getElementById('viewer');
const progressEl = document.getElementById('progress');
const previewEl = document.getElementById('preview') as HTMLImageElement | null;
const dropzoneEl = document.getElementById('dropzone');
const fileInputEl = document.getElementById('file-input') as HTMLInputElement | null;
const statusEl = document.getElementById('status');

if (!viewerEl || !progressEl || !previewEl || !dropzoneEl || !fileInputEl || !statusEl) {
  throw new Error('hmwebviewer: required DOM elements missing');
}

const onError = (msg: string) => setStatus(statusEl, msg);

let viewer: ThreeDViewer;
try {
  viewer = new ThreeDViewer(viewerEl, progressEl, previewEl, onError);
} catch (err) {
  console.error('[hmwebviewer] init failed', err);
  setStatus(statusEl, 'WebGL is required but unavailable in this browser.');
  throw err;
}

initDropzone({
  viewer,
  dropzone: dropzoneEl,
  fileInput: fileInputEl,
  onError: (msg) => { console.warn('[hmwebviewer]', msg); setStatus(statusEl, msg); },
});

// Viewer controls — Zoom Fit, projection toggle, outline overlay
document.getElementById('btn-fit')?.addEventListener('click', () => viewer.fitView());

const perspBtn = document.getElementById('btn-persp');
const orthoBtn = document.getElementById('btn-ortho');
const setProjection = (mode: 'persp' | 'ortho') => {
  viewer.setProjection(mode);
  perspBtn?.classList.toggle('active', mode === 'persp');
  orthoBtn?.classList.toggle('active', mode === 'ortho');
};
perspBtn?.addEventListener('click', () => setProjection('persp'));
orthoBtn?.addEventListener('click', () => setProjection('ortho'));

const outlineBtn = document.getElementById('btn-outline');
outlineBtn?.addEventListener('click', () => {
  const on = viewer.toggleOutline();
  outlineBtn.classList.toggle('active', on);
});

// Path A (server asset) — opt-in via ?model=<url>
const modelUrl = new URLSearchParams(window.location.search).get('model');
if (modelUrl) {
  // SSR placeholder: a pre-rendered 360° animated WebP (tools/prerender.mjs)
  // shows instantly, then the hydration gate fades it out once WebGL + model ready.
  const base = modelUrl.split('/').pop()!.replace(/\.(glb|gltf|obj|fbx|dae|ifc|ply)$/i, '');
  previewEl.src = publicAssetUrl(`previews/${base}.webp`);
  previewEl.classList.remove('hidden');
  previewEl.onerror = () => previewEl.classList.add('hidden');
  viewer.loadServerAsset(modelUrl);
}

// tools/prerender.mjs가 회전 frame을 캡처할 때 사용하는 공개 reference입니다.
const viewerWindow = window as Window & { __viewer?: ThreeDViewer };
viewerWindow.__viewer = viewer;

window.addEventListener(
  'pagehide',
  () => {
    viewer.dispose();
    delete viewerWindow.__viewer;
  },
  { once: true },
);
