# StreamLayerSDKTv Pause Ad Integration

> **Alpha Version**: This feature is currently in alpha. Expect potential instability, including occasional freezes.

## Prerequisites

### 1. PAL SDK

Add the Google PAL SDK to your HTML `<head>`:

```html
<script type="text/javascript" src="https://imasdk.googleapis.com/pal/sdkloader/pal.js"></script>
```

### 2. Spatial Navigation

This feature uses [@noriginmedia/norigin-spatial-navigation](https://github.com/nicetechnologies/norigin-spatial-navigation) with `shouldFocusDOMNode: true` mode for remote control support.

---

## Integration

### Props

| Prop | Type | Description |
|------|------|-------------|
| `showPauseAd` | `boolean` | Controls pause ad visibility. Set to `true` when video pauses. |
| `onRenderPauseAd` | `(params: { rendered: boolean }) => void` | Called when pause ad overlay renders. Use to hide your UI elements. |
| `onClosePauseAd` | `() => void` | Called when pause ad closes without resuming video (user dismissed overlay). |
| `videoPlayerController` | `VideoPlayerCallback` | Called when user resumes video via the pause ad overlay button. |
| `pauseAdVastUrl` | `Array<{ template: string; url: string }>` | VAST tag configuration. |

### pauseAdVastUrl Configuration

```typescript
pauseAdVastUrl={[
  {
    template: 'default', // Currently only 'default' template is supported
    url: 'https://your-vast-tag-url.com/vast.xml',
  },
]}
```

> **Note**: Only the first item in the array is used. Multi-item rotation is not yet supported.

---

## Understanding `showPauseAd` vs `pauseAdRendered`

These two flags serve different purposes and are controlled by different parties:

| Flag | Controlled By | Purpose |
|------|---------------|---------|
| `showPauseAd` | **You (integrator)** | Request to show/hide pause ad |
| `pauseAdRendered` | **SDK (via callback)** | Actual visibility state on screen |

### Why two flags?

**`showPauseAd`** is your *intent* — "I want the pause ad to appear/disappear."

**`pauseAdRendered`** is the *actual state* — "The pause ad is currently visible on screen."

These values don't always match due to **animation delays**:

- **Opening delay (5 seconds)**: SDK waits before showing the overlay
- **Closing delay (400ms)**: SDK animates the overlay before removing it

### State combinations

| `showPauseAd` | `pauseAdRendered` | State |
|---------------|-------------------|-------|
| `false` | `false` | Video playing or paused without ad |
| `true` | `false` | Video paused, SDK preparing overlay (5s delay) |
| `true` | `true` | Pause ad visible on screen |
| `false` | `true` | **Closing animation in progress (400ms)** |

### Timeline

```
Video pauses
    │
    ▼
showPauseAd = true              ← You set this on video pause
pauseAdRendered = false
    │
    │  ← 5 second delay (SDK loads ad, prepares overlay)
    ▼
showPauseAd = true
pauseAdRendered = true          ← SDK calls onRenderPauseAd({ rendered: true })
                                  Hide your UI controls now
    │
    │  ← User resumes video or closes overlay
    ▼
showPauseAd = false             ← You set this on play/close
pauseAdRendered = true          ← Still true! Closing animation playing
    │
    │  ← 400ms closing animation
    ▼
showPauseAd = false
pauseAdRendered = false         ← SDK calls onRenderPauseAd({ rendered: false })
                                  Safe to show your UI controls
```

### Why this matters

Always use `pauseAdRendered` to control your UI visibility:

```tsx
// Correct: hide UI based on actual render state
const showControls = !pauseAdRendered

// This ensures:
// 1. Your controls don't disappear 5s before the ad appears
// 2. Your controls don't reappear during the 400ms closing animation
```

If you used `showPauseAd` instead, your controls would:
- Disappear immediately on pause (5s before the ad shows)
- Reappear during the closing animation (overlapping with the ad)

---

## Implementation Example

```tsx
import { useState, useCallback, useRef } from 'react'
import { StreamLayerSDKTv, type VideoPlayerCallback } from '@streamlayer/sdk-web-os'

export const VideoView = () => {
  const [showPauseAd, setShowPauseAd] = useState(false)
  const [pauseAdRendered, setPauseAdRendered] = useState(false)
  const videoRef = useRef<HTMLVideoElement>(null)

  // Called when pause ad overlay renders/hides
  const onRenderPauseAd = useCallback((params: { rendered: boolean }) => {
    setPauseAdRendered(params.rendered)
  }, [])

  // Called when pause ad closes without video resumption
  const onClosePauseAd = useCallback(() => {
    setShowPauseAd(false)
  }, [])

  // Called when user clicks resume on pause ad overlay
  const videoPlayerController: VideoPlayerCallback = useCallback((data) => {
    if (data.play === true) {
      videoRef.current?.play()
    }
  }, [])

  // Video event handlers
  const onVideoPause = useCallback(() => {
    setShowPauseAd(true)
  }, [])

  const onVideoPlay = useCallback(() => {
    setShowPauseAd(false)
  }, [])

  // Hide your UI controls when pause ad is rendered
  const showControls = !pauseAdRendered

  return (
    <StreamLayerSDKTv
      showPauseAd={showPauseAd}
      onRenderPauseAd={onRenderPauseAd}
      onClosePauseAd={onClosePauseAd}
      videoPlayerController={videoPlayerController}
      pauseAdVastUrl={[
        {
          template: 'default',
          url: 'https://your-vast-tag-url.com',
        },
      ]}
    >
      {/* Your video container */}
      <div>
        <video
          ref={videoRef}
          onPause={onVideoPause}
          onPlay={onVideoPlay}
        />

        {/* Hide controls when pause ad is displayed */}
        {showControls && (
          <div className="video-controls">
            {/* Play button, timeline, etc. */}
          </div>
        )}
      </div>
    </StreamLayerSDKTv>
  )
}
```

---

## Lifecycle Flow

```
Video Pauses
     │
     ▼
setShowPauseAd(true) ──► StreamLayerSDKTv receives showPauseAd=true
                                      │
                                      ▼
                         onRenderPauseAd({ rendered: true })
                                      │
                                      ▼
                         Hide your UI (controls, timeline, etc.)
                                      │
              ┌───────────────────────┴───────────────────────┐
              ▼                                               ▼
     User clicks RESUME                              User closes overlay
              │                                               │
              ▼                                               ▼
videoPlayerController({ play: true })                 onClosePauseAd()
              │                                               │
              ▼                                               ▼
     Resume video playback                        setShowPauseAd(false)
     setShowPauseAd(false)                        (video stays paused)
```

---

## Key Points

1. **You control `showPauseAd`**: Set it to `true` on video pause, `false` on play/resume.
2. **Hide UI on render**: When `onRenderPauseAd` fires with `rendered: true`, hide your video controls (play button, timeline, etc.).
3. **Handle both exit paths**: User can either resume video (via `videoPlayerController`) or dismiss the overlay (via `onClosePauseAd`).
4. **Single VAST tag**: Only one item in `pauseAdVastUrl` is processed; additional items are ignored.
