import { ScreenShareQualityPreset, ScreenShareStartOptions } from '../../screen-share.config';
import { WebRTCLogger } from '../../logging/webrtc-logger';
import { getElectronApi } from '../../../../core/platform/electron/get-electron-api';

export class BrowserScreenShareCapture {
  constructor(private readonly logger: WebRTCLogger) {}

  async startCapture(
    options: ScreenShareStartOptions,
    preset: ScreenShareQualityPreset
  ): Promise<MediaStream> {
    const displayConstraints = this.buildDisplayMediaConstraints(options, preset);

    this.logger.info('getDisplayMedia constraints', displayConstraints);

    if (!navigator.mediaDevices?.getDisplayMedia) {
      throw new Error('navigator.mediaDevices.getDisplayMedia is not available.');
    }

    const stream = await navigator.mediaDevices.getDisplayMedia(displayConstraints);

    this.logAudioTrackSettings(stream);

    return stream;
  }

  private buildDisplayMediaConstraints(
    options: ScreenShareStartOptions,
    preset: ScreenShareQualityPreset
  ): DisplayMediaStreamOptions {
    const supportedConstraints = navigator.mediaDevices?.getSupportedConstraints?.() as Record<string, boolean> | undefined;
    const isWindowsElectron = this.isWindowsElectron();
    const audioConstraints: Record<string, unknown> | false = options.includeSystemAudio
      ? {
        echoCancellation: false,
        noiseSuppression: false,
        autoGainControl: false
      }
      : false;

    if (audioConstraints && supportedConstraints?.['restrictOwnAudio']) {
      audioConstraints['restrictOwnAudio'] = true;
    }

    if (audioConstraints && supportedConstraints?.['suppressLocalAudioPlayback']) {
      // Windows Electron should keep voice playback audible to the sharer.
      // Use own-audio restriction to keep the app's playback out of the
      // captured stream instead of muting local playback.
      audioConstraints['suppressLocalAudioPlayback'] = !isWindowsElectron;
    }

    return {
      video: {
        width: { ideal: preset.width, max: preset.width },
        height: { ideal: preset.height, max: preset.height },
        frameRate: { ideal: preset.frameRate, max: preset.frameRate }
      },
      audio: audioConstraints,
      monitorTypeSurfaces: 'include',
      selfBrowserSurface: 'exclude',
      surfaceSwitching: 'include',
      systemAudio: options.includeSystemAudio ? 'include' : 'exclude'
    } as DisplayMediaStreamOptions;
  }

  private logAudioTrackSettings(stream: MediaStream): void {
    const audioTrack = stream.getAudioTracks()[0];

    if (!audioTrack || typeof audioTrack.getSettings !== 'function') {
      return;
    }

    const settings = audioTrack.getSettings() as MediaTrackSettings & {
      restrictOwnAudio?: boolean;
      suppressLocalAudioPlayback?: boolean;
    };

    this.logger.info('getDisplayMedia audio track settings', {
      restrictOwnAudio: settings.restrictOwnAudio ?? null,
      suppressLocalAudioPlayback: settings.suppressLocalAudioPlayback ?? null
    });
  }

  private isWindowsElectron(): boolean {
    if (typeof window === 'undefined' || typeof navigator === 'undefined') {
      return false;
    }

    return !!getElectronApi()
      && /win/i.test(`${navigator.userAgent} ${navigator.platform}`);
  }
}
