@extends('layouts.overlay')

@section('title', 'GAME')

@section('body-class', 'camera-hud-body')

@section('styles')
<style>
  :root {
    --pad-y: 40px;
    --pad-x: 72px;
    /* Camera frame defaults — auto-synced from OBS via WS. */
    --cam-x: 1855px;
    --cam-y: 128px;
    --cam-w: 580px;
    --cam-h: 326px;
    --cam-pad: 10px;
  }
  .hud {
    position: absolute;
    top: var(--pad-y);
    left: var(--pad-x);
    right: var(--pad-x);
    font-size: 20px;
    text-shadow: 0 0 8px rgba(7, 8, 13, 0.9), 0 0 4px rgba(7, 8, 13, 0.9);
  }
  .hud .group { gap: 24px; }
  .hud .group > span { gap: 10px; }
  .hud .led { width: 10px; height: 10px; }
</style>
@endsection

@push('data-scripts')
<script>window.__LOADING = @json($manifest);</script>
@endpush

@section('crt')
{{-- no CRT overlays on the transparent game HUD --}}
@endsection

@section('content')
  @include('partials.hud-strip', [
    'variant' => 'live',
    'idText'  => 'OPHI-118 // LIVE',
  ])

  @include('partials.camera-frame', ['id' => 'cam', 'label' => 'CAM 01'])

  <footer class="status-bar">
    <div class="status-line">
      <div class="live-block">
        <span class="live-dot"></span>
        <span>LIVE</span>
      </div>
      <span class="sep">·</span>
      <span class="game-name" id="game-name">—</span>
      <span class="sep" id="game-mode-sep">·</span>
      <span class="game-mode" id="game-mode">—</span>
    </div>
    <div class="status-line meta-line">
      <span class="icon">◷</span>
      <span class="elapsed" id="elapsed">00:00:00</span>
      <span class="sep">·</span>
      <span class="icon" id="mic-icon" title="microphone">🎙</span>
      <span id="mic-state">—</span>
      <span class="sep">·</span>
      <div class="np-block" id="np">
        <span class="arrow">▶</span>
        <span class="title" id="np-title">—</span>
        <span class="time"  id="np-time">[--:-- / --:--]</span>
      </div>
    </div>
  </footer>
@endsection

@section('scripts')
<script>
  'use strict';
  const pad = HUD.pad;

  const m = window.__LOADING || {};
  const gameName = (m.game || '—').toUpperCase();
  const subtitle = m.subtitle ? m.subtitle.toUpperCase() : null;
  const cameraOn = m.camera ?? true;
  const micOn    = m.microphone ?? true;

  document.getElementById('game-name').textContent = gameName;
  if (subtitle) {
    document.getElementById('game-mode').textContent = subtitle;
  } else {
    document.getElementById('game-mode-sep').style.display = 'none';
    document.getElementById('game-mode').style.display = 'none';
  }
  const micEl = document.getElementById('mic-state');
  micEl.textContent = micOn ? 'ON' : 'MUTED';
  micEl.style.color = micOn ? 'var(--term-fg)' : 'var(--accent)';
  if (!cameraOn) document.getElementById('cam').classList.add('off');

  const streamStart = Date.now();
  function tickElapsed() {
    const s = Math.floor((Date.now() - streamStart) / 1000);
    const h = Math.floor(s / 3600);
    const mm = Math.floor((s / 60) % 60);
    const ss = s % 60;
    document.getElementById('elapsed').textContent = `${pad(h)}:${pad(mm)}:${pad(ss)}`;
  }
  tickElapsed(); setInterval(tickElapsed, 1000);

  const params       = new URLSearchParams(location.search);
  const CAM_SOURCE   = params.get('camera') || 'Camera';
  const CAM_SCENE    = params.get('scene')  || 'Game';

  function fmtTime(s) {
    if (!isFinite(s) || s < 0) return '--:--';
    return `${pad(Math.floor(s / 60))}:${pad(Math.floor(s % 60))}`;
  }
  const npBlock = document.getElementById('np');
  const npTitle = document.getElementById('np-title');
  const npTime  = document.getElementById('np-time');
  const camEl   = document.getElementById('cam');
  const rootStyle = document.documentElement.style;
  const setCameraVisible = (visible) => camEl.classList.toggle('off', !visible);
  function setCameraTransform(t) {
    if (!t) return;
    const w = (t.sourceWidth  ?? 0) * (t.scaleX ?? 1);
    const h = (t.sourceHeight ?? 0) * (t.scaleY ?? 1);
    if (!(w > 0 && h > 0)) return;
    rootStyle.setProperty('--cam-x', `${t.positionX}px`);
    rootStyle.setProperty('--cam-y', `${t.positionY}px`);
    rootStyle.setProperty('--cam-w', `${w}px`);
    rootStyle.setProperty('--cam-h', `${h}px`);
  }

  async function syncCamera(obs) {
    let camItemId = null;
    try {
      const r = await obs.call('GetSceneItemId',
        { sceneName: CAM_SCENE, sourceName: CAM_SOURCE });
      camItemId = r.sceneItemId;
      const e = await obs.call('GetSceneItemEnabled',
        { sceneName: CAM_SCENE, sceneItemId: camItemId });
      setCameraVisible(e.sceneItemEnabled);
      const t = await obs.call('GetSceneItemTransform',
        { sceneName: CAM_SCENE, sceneItemId: camItemId });
      setCameraTransform(t.sceneItemTransform);
    } catch (err) {
      console.warn(`[game] camera sync init failed (${CAM_SCENE}/${CAM_SOURCE}):`, err.message);
      return;
    }
    obs.addEventListener('event', (ev) => {
      const d = ev.detail || {};
      if (d.eventData?.sceneName !== CAM_SCENE
          || d.eventData?.sceneItemId !== camItemId) return;
      if (d.eventType === 'SceneItemEnableStateChanged') {
        setCameraVisible(d.eventData.sceneItemEnabled);
      } else if (d.eventType === 'SceneItemTransformChanged') {
        setCameraTransform(d.eventData.sceneItemTransform);
      }
    });
  }

  OBSWSBootstrap.connect({
    onConnect: async (obs) => {
      obs.onCustom('mpd:state', (s) => {
        if (!s.title) return;
        npBlock.classList.add('on');
        npTitle.textContent = s.title;
        npTime.textContent  = `[${fmtTime(s.currentTime)} / ${fmtTime(s.duration)}]`;
      });
      await syncCamera(obs);
    },
    onClose: () => npBlock.classList.remove('on'),
  });
</script>
@endsection
