import { Observable } from 'rxjs';
import { ChatEvent } from '../../../shared-kernel';
import { ScreenShareStartOptions } from '../screen-share.config';
import { PeerData } from '../realtime.types';
import { MediaManager } from '../media/media.manager';
import { PeerConnectionManager } from '../peer-connection-manager/peer-connection.manager';
import { ScreenShareManager } from '../media/screen-share.manager';

interface PeerMediaFacadeDependencies {
  peerManager: PeerConnectionManager;
  mediaManager: MediaManager;
  screenShareManager: ScreenShareManager;
}

export class PeerMediaFacade {
  constructor(
    private readonly dependencies: PeerMediaFacadeDependencies
  ) {}

  get onMessageReceived(): Observable<ChatEvent> {
    return this.dependencies.peerManager.messageReceived$.asObservable();
  }

  get onPeerConnected(): Observable<string> {
    return this.dependencies.peerManager.peerConnected$.asObservable();
  }

  get onPeerDisconnected(): Observable<string> {
    return this.dependencies.peerManager.peerDisconnected$.asObservable();
  }

  get onRemoteStream(): Observable<{ peerId: string; stream: MediaStream }> {
    return this.dependencies.peerManager.remoteStream$.asObservable();
  }

  get onVoiceConnected(): Observable<void> {
    return this.dependencies.mediaManager.voiceConnected$.asObservable();
  }

  getActivePeers(): Map<string, PeerData> {
    return this.dependencies.peerManager.activePeerConnections;
  }

  async renegotiate(peerId: string): Promise<void> {
    return await this.dependencies.peerManager.renegotiate(peerId);
  }

  broadcastMessage(event: ChatEvent): void {
    this.dependencies.peerManager.broadcastMessage(event);
  }

  sendToPeer(peerId: string, event: ChatEvent): void {
    this.dependencies.peerManager.sendToPeer(peerId, event);
  }

  async sendToPeerBuffered(peerId: string, event: ChatEvent): Promise<void> {
    return await this.dependencies.peerManager.sendToPeerBuffered(peerId, event);
  }

  broadcastCurrentStates(): void {
    this.dependencies.peerManager.broadcastCurrentStates();
  }

  getConnectedPeerIds(): string[] {
    return this.dependencies.peerManager.getConnectedPeerIds();
  }

  getRemoteStream(peerId: string): MediaStream | null {
    return this.dependencies.peerManager.remotePeerStreams.get(peerId) ?? null;
  }

  getRemoteVoiceStream(peerId: string): MediaStream | null {
    return this.dependencies.peerManager.remotePeerVoiceStreams.get(peerId) ?? null;
  }

  getRemoteCameraStream(peerId: string): MediaStream | null {
    return this.dependencies.peerManager.remotePeerCameraStreams.get(peerId) ?? null;
  }

  getRemoteScreenShareStream(peerId: string): MediaStream | null {
    return this.dependencies.peerManager.remotePeerScreenShareStreams.get(peerId) ?? null;
  }

  clearRemoteScreenShareStream(peerId: string): void {
    this.dependencies.peerManager.clearRemoteScreenShareStream(peerId);
  }

  closeAllPeers(): void {
    this.dependencies.peerManager.closeAllPeers();
  }

  getLocalStream(): MediaStream | null {
    return this.dependencies.mediaManager.getLocalStream();
  }

  getLocalCameraStream(): MediaStream | null {
    return this.dependencies.mediaManager.getLocalCameraStream();
  }

  getRawMicStream(): MediaStream | null {
    return this.dependencies.mediaManager.getRawMicStream();
  }

  isScreenShareActive(): boolean {
    return this.dependencies.screenShareManager.getIsScreenActive();
  }

  async startScreenShare(options: ScreenShareStartOptions): Promise<MediaStream> {
    return await this.dependencies.screenShareManager.startScreenShare(options);
  }

  stopScreenShare(): void {
    this.dependencies.screenShareManager.stopScreenShare();
  }

  requestScreenShareForPeer(peerId: string): void {
    this.dependencies.screenShareManager.requestScreenShareForPeer(peerId);
  }

  stopScreenShareForPeer(peerId: string): void {
    this.dependencies.screenShareManager.stopScreenShareForPeer(peerId);
  }

  clearScreenShareRequest(peerId: string): void {
    this.dependencies.screenShareManager.clearScreenShareRequest(peerId);
  }

  syncScreenShareToPeer(peerId: string): void {
    this.dependencies.screenShareManager.syncScreenShareToPeer(peerId);
  }

  destroy(): void {
    this.dependencies.peerManager.destroy();
    this.dependencies.mediaManager.destroy();
    this.dependencies.screenShareManager.destroy();
  }
}
