# Type Synchronization & Thread Safety

## PlayerState (Rust <-> TypeScript)

**Rust:**
```rust
pub enum PlayerState {
    Idle,
    Loading { media: MediaItem },
    Playing { media: MediaItem, position: f64, duration: f64 },
    Paused { media: MediaItem, position: f64, duration: f64 },
    Seeking { media: MediaItem, target: f64 },
    Error { media: Option<MediaItem>, error: String },
}
```

**TypeScript:**
```typescript
type PlayerState =
  | { kind: "idle" }
  | { kind: "loading"; media: MediaItem }
  | { kind: "playing"; media: MediaItem; position: number; duration: number }
  | { kind: "paused"; media: MediaItem; position: number; duration: number }
  | { kind: "seeking"; media: MediaItem; target: number }
  | { kind: "error"; media: MediaItem | null; error: string };
```

## MediaItem Serialization

```rust
// Rust (serde serialization)
#[derive(Serialize, Deserialize)]
pub struct MediaItem {
    pub id: String,
    pub title: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub artist: Option<String>,
    // ...
}
```

```typescript
// TypeScript
interface MediaItem {
  id: string;
  title: string;
  artist?: string;
  // ...
}
```

## Tauri v2 IPC Parameter Naming Convention

**CRITICAL**: Tauri v2's `#[tauri::command]` macro automatically converts snake_case Rust parameter names to camelCase for the frontend. All `invoke()` calls must use camelCase for top-level parameters.

**Rule**: Rust `fn cmd(repository_handle: String)` -> Frontend sends `{ repositoryHandle: "..." }`

```typescript
// CORRECT - Tauri v2 auto-converts snake_case -> camelCase
await invoke("player_play_tracks", {
  repositoryHandle: "handle-123",     // Rust: repository_handle
  request: { trackIds: ["id1"], startIndex: 0 }
});

await invoke("remote_send_command", {
  sessionId: "session-123",           // Rust: session_id
  command: "PlayPause"
});

await invoke("pin_item", {
  itemId: "item-123"                  // Rust: item_id
});

// WRONG - snake_case causes "invalid args request" error on Android
await invoke("player_play_tracks", {
  repository_handle: "handle-123",    // Will fail!
});
```

**Parameter Name Mapping (Rust -> Frontend)**:

| Rust Parameter | Frontend Parameter | Used By |
|----------------|-------------------|----|
| `repository_handle` | `repositoryHandle` | `player_play_tracks`, `player_add_track_by_id`, `player_play_album_track` |
| `session_id` | `sessionId` | `remote_send_command`, `remote_play_on_session`, `remote_session_seek` |
| `item_id` | `itemId` | `pin_item`, `unpin_item` |
| `current_item_id` | `currentItemId` | `playback_mode_transfer_to_local` |
| `position_ticks` | `positionTicks` | `playback_mode_transfer_to_local`, `remote_session_seek` |
| `item_ids` | `itemIds` | `remote_play_on_session` |
| `start_index` | `startIndex` | `remote_play_on_session` |

**Nested struct fields** use `#[serde(rename_all = "camelCase")]` separately - this is serde deserialization, not the command macro. Both layers convert independently.

**Test Coverage**: Integration tests in `src/lib/utils/tauriIntegration.test.ts` validate all invoke calls use correct camelCase parameter names.

## Rust Backend Thread Safety

```rust
// Shared state wrapped in Arc<Mutex<>>
pub struct PlayerController {
    backend: Arc<Mutex<Box<dyn PlayerBackend>>>,
    queue: Arc<Mutex<QueueManager>>,
    // ...
}

// Tauri state wrapper
pub struct PlayerStateWrapper(pub Mutex<PlayerController>);

// Command handler pattern
#[tauri::command]
pub fn player_play(state: State<PlayerStateWrapper>) -> Result<PlayerStatus, String> {
    let mut controller = state.0.lock().unwrap();  // Acquire lock
    controller.play()?;                             // Operate
    Ok(get_player_status(&controller))              // Lock released
}
```

## Frontend Stores

Svelte stores are inherently reactive and thread-safe for UI updates:

```typescript
const { subscribe, update } = writable<PlayerStore>(initialState);

// Atomic updates
function setPlaying(media: MediaItem, position: number, duration: number) {
  update(state => ({
    ...state,
    state: { kind: "playing", media, position, duration }
  }));
}
```
