import type { ServerWebSocket } from "bun";

export interface Track {
  filename: string;
  title: string;
  duration: number;
}

export interface StreamConfig {
  id: string;
  name: string;
  tracks: Track[];
}

export class Stream {
  id: string;
  name: string;
  playlist: Track[];
  currentIndex: number = 0;
  startedAt: number = Date.now();
  clients: Set<ServerWebSocket<{ streamId: string }>> = new Set();
  paused: boolean = false;
  pausedAt: number = 0;

  constructor(config: StreamConfig) {
    this.id = config.id;
    this.name = config.name;
    this.playlist = config.tracks;
  }

  get currentTrack(): Track | null {
    if (this.playlist.length === 0) return null;
    return this.playlist[this.currentIndex];
  }

  get currentTimestamp(): number {
    if (this.paused) return this.pausedAt;
    return (Date.now() - this.startedAt) / 1000;
  }

  tick(): boolean {
    if (this.paused) return false;
    const track = this.currentTrack;
    if (!track) return false;
    if (this.currentTimestamp >= track.duration) {
      this.advance();
      return true;
    }
    return false;
  }

  advance() {
    if (this.playlist.length === 0) return;
    this.currentIndex = (this.currentIndex + 1) % this.playlist.length;
    this.startedAt = Date.now();
    this.broadcast();
  }

  getState() {
    return {
      track: this.currentTrack,
      currentTimestamp: this.currentTimestamp,
      streamName: this.name,
      paused: this.paused,
    };
  }

  pause() {
    if (this.paused) return;
    this.pausedAt = this.currentTimestamp;
    this.paused = true;
    this.broadcast();
  }

  unpause() {
    if (!this.paused) return;
    this.paused = false;
    this.startedAt = Date.now() - this.pausedAt * 1000;
    this.broadcast();
  }

  broadcast() {
    const msg = JSON.stringify(this.getState());
    for (const ws of this.clients) {
      ws.send(msg);
    }
  }

  addClient(ws: ServerWebSocket<{ streamId: string }>) {
    this.clients.add(ws);
    ws.send(JSON.stringify(this.getState()));
  }

  removeClient(ws: ServerWebSocket<{ streamId: string }>) {
    this.clients.delete(ws);
  }
}
