import { Injectable, inject } from '@angular/core';
import { ChatEvent } from '../../../../shared-kernel';
import { RealtimeSessionFacade } from '../../../../core/realtime';
import { LatencyProfile } from '../../domain/models/voice-connection.model';

@Injectable({ providedIn: 'root' })
export class VoiceConnectionFacade {
  readonly isVoiceConnected = inject(RealtimeSessionFacade).isVoiceConnected;
  readonly isMuted = inject(RealtimeSessionFacade).isMuted;
  readonly isDeafened = inject(RealtimeSessionFacade).isDeafened;
  readonly isCameraEnabled = inject(RealtimeSessionFacade).isCameraEnabled;
  readonly isNoiseReductionEnabled = inject(RealtimeSessionFacade).isNoiseReductionEnabled;
  readonly hasConnectionError = inject(RealtimeSessionFacade).hasConnectionError;
  readonly connectionErrorMessage = inject(RealtimeSessionFacade).connectionErrorMessage;
  readonly shouldShowConnectionError = inject(RealtimeSessionFacade).shouldShowConnectionError;
  readonly peerLatencies = inject(RealtimeSessionFacade).peerLatencies;
  readonly onRemoteStream = inject(RealtimeSessionFacade).onRemoteStream;
  readonly onPeerConnected = inject(RealtimeSessionFacade).onPeerConnected;
  readonly onPeerDisconnected = inject(RealtimeSessionFacade).onPeerDisconnected;
  readonly onVoiceConnected = inject(RealtimeSessionFacade).onVoiceConnected;

  private readonly realtime = inject(RealtimeSessionFacade);

  async ensureSignalingConnected(timeoutMs?: number): Promise<boolean> {
    return await this.realtime.ensureSignalingConnected(timeoutMs);
  }

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

  getConnectedPeers(): string[] {
    return this.realtime.getConnectedPeers();
  }

  getRemoteVoiceStream(peerId: string): MediaStream | null {
    return this.realtime.getRemoteVoiceStream(peerId);
  }

  getRemoteCameraStream(peerId: string): MediaStream | null {
    return this.realtime.getRemoteCameraStream(peerId);
  }

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

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

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

  reportConnectionError(message: string): void {
    this.realtime.reportConnectionError(message);
  }

  clearConnectionError(): void {
    this.realtime.clearConnectionError();
  }

  async enableVoice(): Promise<MediaStream> {
    return await this.realtime.enableVoice();
  }

  disableVoice(): void {
    this.realtime.disableVoice();
  }

  async enableCamera(): Promise<MediaStream> {
    return await this.realtime.enableCamera();
  }

  disableCamera(): void {
    this.realtime.disableCamera();
  }

  async setLocalStream(stream: MediaStream): Promise<void> {
    await this.realtime.setLocalStream(stream);
  }

  toggleMute(muted?: boolean): void {
    this.realtime.toggleMute(muted);
  }

  toggleDeafen(deafened?: boolean): void {
    this.realtime.toggleDeafen(deafened);
  }

  async toggleNoiseReduction(enabled?: boolean): Promise<void> {
    await this.realtime.toggleNoiseReduction(enabled);
  }

  setOutputVolume(volume: number): void {
    this.realtime.setOutputVolume(volume);
  }

  setInputVolume(volume: number): void {
    this.realtime.setInputVolume(volume);
  }

  async setAudioBitrate(kbps: number): Promise<void> {
    await this.realtime.setAudioBitrate(kbps);
  }

  async setLatencyProfile(profile: LatencyProfile): Promise<void> {
    await this.realtime.setLatencyProfile(profile);
  }

  startVoiceHeartbeat(roomId?: string, serverId?: string): void {
    this.realtime.startVoiceHeartbeat(roomId, serverId);
  }

  stopVoiceHeartbeat(): void {
    this.realtime.stopVoiceHeartbeat();
  }

  syncOutgoingVoiceRouting(allowedPeerIds: string[]): void {
    this.realtime.syncOutgoingVoiceRouting(allowedPeerIds);
  }
}
