# VideoPlayer

Unified video player component supporting multiple modes and source types.

## Modes

| Mode | Source Types | Use Case |
|------|-------------|----------|
| `vidstack` | YouTube, Vimeo, HLS, DASH | Full-featured player with themes and controls |
| `native` | URL, data-url | Lightweight HTML5 player |
| `streaming` | stream, blob | HTTP Range streaming with auth, binary data |

Mode is auto-detected from source type, or can be forced via `mode` prop.

## Installation

```tsx
import {
  VideoPlayer,
  VideoPlayerProvider,
  VideoErrorFallback,
  resolveFileSource
} from '@djangocfg/ui-nextjs';
```

## Basic Usage

### YouTube / Vimeo

```tsx
<VideoPlayer source={{ type: 'youtube', id: 'dQw4w9WgXcQ' }} />
<VideoPlayer source={{ type: 'vimeo', id: '123456789' }} />
```

### HLS / DASH Streaming

```tsx
<VideoPlayer source={{ type: 'hls', url: 'https://example.com/video.m3u8' }} />
<VideoPlayer source={{ type: 'dash', url: 'https://example.com/video.mpd' }} />
```

### Direct URL

```tsx
<VideoPlayer source={{ type: 'url', url: 'https://example.com/video.mp4' }} />
```

### HTTP Range Streaming (with auth)

```tsx
// Full source (standalone)
<VideoPlayer
  source={{
    type: 'stream',
    sessionId: 'abc123',
    path: '/videos/movie.mp4',
    getStreamUrl: (id, path) => `/api/stream/${id}?path=${path}&token=${token}`
  }}
/>

// Simplified source (with context)
<VideoPlayerProvider sessionId={sessionId} getStreamUrl={getStreamUrl}>
  <VideoPlayer source={{ type: 'stream', path: '/videos/movie.mp4' }} />
</VideoPlayerProvider>
```

### Blob / ArrayBuffer

```tsx
<VideoPlayer
  source={{
    type: 'blob',
    data: arrayBuffer,
    mimeType: 'video/mp4'
  }}
/>
```

## Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `source` | `VideoSourceUnion` | required | Video source configuration |
| `mode` | `'auto' \| 'vidstack' \| 'native' \| 'streaming'` | `'auto'` | Force specific player mode |
| `aspectRatio` | `number \| 'auto' \| 'fill'` | `16/9` | Aspect ratio or fill parent |
| `autoPlay` | `boolean` | `false` | Auto-play on load |
| `muted` | `boolean` | `false` | Muted by default |
| `loop` | `boolean` | `false` | Loop playback |
| `controls` | `boolean` | `true` | Show player controls |
| `playsInline` | `boolean` | `true` | Inline playback on mobile |
| `preload` | `'none' \| 'metadata' \| 'auto'` | `'metadata'` | Preload strategy |
| `theme` | `'default' \| 'minimal' \| 'modern'` | `'default'` | Vidstack theme |
| `errorFallback` | `ReactNode \| (props) => ReactNode` | - | Custom error UI |
| `className` | `string` | - | Container className |
| `videoClassName` | `string` | - | Video element className |

## Events

| Event | Type | Description |
|-------|------|-------------|
| `onPlay` | `() => void` | Playback started |
| `onPause` | `() => void` | Playback paused |
| `onEnded` | `() => void` | Playback ended |
| `onError` | `(error: string) => void` | Error occurred |
| `onLoadStart` | `() => void` | Loading started |
| `onCanPlay` | `() => void` | Ready to play |
| `onTimeUpdate` | `(time: number, duration: number) => void` | Time updated |

## Ref API

```tsx
const playerRef = useRef<VideoPlayerRef>(null);

<VideoPlayer ref={playerRef} source={source} />

// Control methods
playerRef.current?.play();
playerRef.current?.pause();
playerRef.current?.seek(30);        // Seek to 30 seconds
playerRef.current?.setVolume(0.5);  // 0-1
playerRef.current?.setMuted(true);
playerRef.current?.reload();
```

## Error Handling

### Custom Error Fallback

```tsx
<VideoPlayer
  source={source}
  errorFallback={(props) => (
    <div>
      <p>Error: {props.error}</p>
      <button onClick={props.retry}>Retry</button>
    </div>
  )}
/>
```

### Pre-built Error Fallback with Download

```tsx
import { VideoErrorFallback } from '@djangocfg/ui-nextjs';

<VideoPlayer
  source={source}
  errorFallback={(props) => (
    <VideoErrorFallback
      {...props}
      downloadUrl={getDownloadUrl()}
      downloadFilename="video.mp4"
      fileSize="125 MB"
    />
  )}
/>
```

## Fill Mode

Use `aspectRatio="fill"` to fill the parent container:

```tsx
<div className="absolute inset-0">
  <VideoPlayer source={source} aspectRatio="fill" />
</div>
```

## Context Provider

For apps with multiple streaming videos, use the context to avoid repetition:

```tsx
// In layout or parent component
<VideoPlayerProvider
  sessionId={sessionId}
  getStreamUrl={(id, path) => `/api/stream/${id}?path=${path}`}
>
  {/* All nested VideoPlayers use this config */}
  <VideoPlayer source={{ type: 'stream', path: '/video1.mp4' }} />
  <VideoPlayer source={{ type: 'stream', path: '/video2.mp4' }} />
</VideoPlayerProvider>
```

## File Source Helper

For file browser integration:

```tsx
import { resolveFileSource } from '@djangocfg/ui-nextjs';

const source = resolveFileSource({
  file: { name: 'movie.mp4', path: '/videos/movie.mp4' },
  sessionId: 'abc123',
  getStreamUrl: (id, path) => `/api/stream/${id}?path=${path}`,
});

if (source) {
  return <VideoPlayer source={source} />;
}
```

## Source Types Reference

```typescript
type VideoSourceUnion =
  | { type: 'url'; url: string; title?: string; poster?: string }
  | { type: 'youtube'; id: string; title?: string; poster?: string }
  | { type: 'vimeo'; id: string; title?: string; poster?: string }
  | { type: 'hls'; url: string; title?: string; poster?: string }
  | { type: 'dash'; url: string; title?: string; poster?: string }
  | { type: 'stream'; sessionId: string; path: string; getStreamUrl: fn; mimeType?: string }
  | { type: 'blob'; data: ArrayBuffer | Blob; mimeType?: string }
  | { type: 'data-url'; data: string; mimeType?: string }
```

## Architecture

```
VideoPlayer/
├── index.ts                    # Public API exports
├── types/
│   ├── index.ts                # Type re-exports
│   ├── sources.ts              # Source types (Url, YouTube, HLS, etc.)
│   ├── player.ts               # Player props, ref, events
│   └── provider.ts             # Provider & context types
├── hooks/
│   ├── index.ts
│   └── useVideoPositionCache.ts  # Playback position caching
├── utils/
│   ├── index.ts
│   ├── resolvers.ts            # resolvePlayerMode, isSimpleStreamSource
│   └── fileSource.ts           # resolveFileSource helper
├── components/
│   ├── index.ts
│   ├── VideoPlayer.tsx         # Main orchestrator
│   ├── VideoControls.tsx       # Standalone Vidstack controls
│   └── VideoErrorFallback.tsx  # Pre-built error UI
├── context/
│   ├── index.ts
│   └── VideoPlayerContext.tsx  # Streaming config provider
└── providers/
    ├── index.ts
    ├── VidstackProvider.tsx    # YouTube, Vimeo, HLS, DASH
    ├── NativeProvider.tsx      # HTML5 <video>
    └── StreamProvider.tsx      # HTTP Range, Blob
```

## Accessibility

Full accessibility support:
- Keyboard navigation (Space, Arrow keys, F for fullscreen)
- Screen reader announcements
- Focus indicators
- ARIA labels and roles

## Browser Support

- Chrome 63+
- Firefox 67+
- Safari 12+
- Edge 79+
- iOS Safari 12+
- Chrome Android 63+
