// src/PermissionManager.ts

export type PermissionState = 'granted' | 'denied' | 'prompt' | 'unavailable';

export class PermissionManager {
  private static instance: PermissionManager;

  private cameraState: PermissionState = 'prompt';
  private microphoneState: PermissionState = 'prompt';

  private cameraListeners: Array<(state: PermissionState) => void> = [];
  private microphoneListeners: Array<(state: PermissionState) => void> = [];

  private constructor() {
    this.init();
  }

  // Méthode pour obtenir l'instance unique (Singleton)
  public static getInstance(): PermissionManager {
    if (!PermissionManager.instance) {
      PermissionManager.instance = new PermissionManager();
    }
    return PermissionManager.instance;
  }

  // Initialisation des permissions
  private async init() {
    await this.checkCameraPermission();
    await this.checkMicrophonePermission();
  }

  // Obtenir l'état actuel de la permission caméra
  public getCameraState(): PermissionState {
    return this.cameraState;
  }

  // Obtenir l'état actuel de la permission microphone
  public getMicrophoneState(): PermissionState {
    return this.microphoneState;
  }

  // Ajouter un écouteur pour les changements de permission caméra
  public addCameraListener(listener: (state: PermissionState) => void) {
    this.cameraListeners.push(listener);
  }

  // Ajouter un écouteur pour les changements de permission microphone
  public addMicrophoneListener(listener: (state: PermissionState) => void) {
    this.microphoneListeners.push(listener);
  }

  // Notifier les écouteurs du changement de permission caméra
  private notifyCameraListeners() {
    this.cameraListeners.forEach((listener) => listener(this.cameraState));
  }

  // Notifier les écouteurs du changement de permission microphone
  private notifyMicrophoneListeners() {
    this.microphoneListeners.forEach((listener) => listener(this.microphoneState));
  }

  // Vérifier l'état de la permission caméra
  private async checkCameraPermission() {
    if (!navigator.permissions) {
      this.cameraState = 'unavailable';
      this.notifyCameraListeners();
      return;
    }

    try {
        const status = await navigator.permissions.query({ name: 'camera' as PermissionName });
        this.cameraState = status.state as PermissionState;
      this.notifyCameraListeners();
      status.onchange = () => {
        this.cameraState = status.state as PermissionState;
        this.notifyCameraListeners();
      };
    } catch (error) {
      console.error('Error checking camera permission:', error);
      this.cameraState = 'unavailable';
      this.notifyCameraListeners();
    }
  }

  // Vérifier l'état de la permission microphone
  private async checkMicrophonePermission() {
    if (!navigator.permissions) {
      this.microphoneState = 'unavailable';
      this.notifyMicrophoneListeners();
      return;
    }

    try {
        const status = await navigator.permissions.query({ name: 'microphone' as PermissionName });
        this.microphoneState = status.state as PermissionState;
      this.notifyMicrophoneListeners();
      status.onchange = () => {
        this.microphoneState = status.state as PermissionState;
        this.notifyMicrophoneListeners();
      };
    } catch (error) {
      console.error('Error checking microphone permission:', error);
      this.microphoneState = 'unavailable';
      this.notifyMicrophoneListeners();
    }
  }
  
  // Demander la permission caméra
public async requestCameraPermission(): Promise<PermissionState> {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: true });
      stream.getTracks().forEach((track) => track.stop());  // Libérer les ressources après la demande
      this.cameraState = 'granted';  // Permission accordée
    } catch (error) {
      console.error('Error requesting camera permission:', error);
      
      if (error instanceof Error && error.name === 'NotAllowedError') {
        this.cameraState = 'denied';  // Permission refusée
        
        // Optionnel : informer l'utilisateur qu'il doit réinitialiser la permission manuellement
        alert('Permission denied. Please enable camera permission in your browser settings.');
      } else {
        this.cameraState = 'unavailable';  // Permission non disponible
        alert('Camera permission is not available.');
      }
    }
    this.notifyCameraListeners();  // Notifier les écouteurs après la mise à jour
    return this.cameraState;  // Retourner l'état actuel
  }
  
  
  // Demander la permission microphone
  public async requestMicrophonePermission(): Promise<PermissionState> {
    try {
      // Essayer de redemander la permission microphone
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      stream.getTracks().forEach((track) => track.stop());  // Libérer les ressources après la demande
      this.microphoneState = 'granted';  // Permission accordée
    } catch (error) {
      console.error('Error requesting microphone permission:', error);
      
      // Gérer les cas où la permission est refusée
      if (error instanceof Error && error.name === 'NotAllowedError') {
        this.microphoneState = 'denied';  // Permission refusée
        alert('Permission denied. Please enable microphone permission in your browser settings.');

      } else {
        this.microphoneState = 'unavailable';  // Permission non disponible
        alert('Microphone permission is not available.');
      }
    }
    this.notifyMicrophoneListeners();  // Notifier les écouteurs après la mise à jour
    return this.microphoneState;  // Retourner l'état actuel
  }
  
}
