// src/components/PermissionStatusDisplay.tsx

import React, { useEffect, useState, useRef } from 'react';
import { useCameraPermission } from '../hooks/useCameraPermission';
import { useMicrophonePermission } from '../hooks/useMicrophonePermission';
import { PermissionStatus } from './PermissionStatus';
import { CameraPermissionButton } from './CameraPermissionButton';
import { MicrophonePermissionButton } from './MicrophonePermissionButton';

export const PermissionStatusDisplay: React.FC = () => {
  const { permissionState: cameraPermissionState } = useCameraPermission();
  const { permissionState: microphonePermissionState } = useMicrophonePermission();

  const [videoDevices, setVideoDevices] = useState<MediaDeviceInfo[]>([]);
  const [audioDevices, setAudioDevices] = useState<MediaDeviceInfo[]>([]);
  const [selectedCamera, setSelectedCamera] = useState<string | null>(null);
  const [selectedMicrophone, setSelectedMicrophone] = useState<string | null>(null);
  const [audioLevel, setAudioLevel] = useState<number>(0);

  const videoRef = useRef<HTMLVideoElement>(null);
  const audioContextRef = useRef<AudioContext | null>(null);
  const analyserRef = useRef<AnalyserNode | null>(null);
  const dataArrayRef = useRef<Uint8Array | null>(null);
  const animationIdRef = useRef<number | null>(null);
  const mediaStreamRef = useRef<MediaStream | null>(null);

  // Fetch available devices on mount
  useEffect(() => {
    const fetchDevices = async () => {
      try {
        const devices = await navigator.mediaDevices.enumerateDevices();
        const videoInputDevices = devices.filter(device => device.kind === 'videoinput');
        const audioInputDevices = devices.filter(device => device.kind === 'audioinput');

        setVideoDevices(videoInputDevices);
        setAudioDevices(audioInputDevices);

        // Set default selections
        if (videoInputDevices.length > 0) {
          setSelectedCamera(videoInputDevices[0].deviceId);
          handleStartVideo(videoInputDevices[0].deviceId);
        }

        if (audioInputDevices.length > 0) {
          setSelectedMicrophone(audioInputDevices[0].deviceId);
          handleStartAudio(audioInputDevices[0].deviceId);
        }
      } catch (error) {
        console.error('Error fetching media devices:', error);
      }
    };

    fetchDevices();

    // Listen for device changes
    navigator.mediaDevices.addEventListener('devicechange', fetchDevices);

    return () => {
      navigator.mediaDevices.removeEventListener('devicechange', fetchDevices);
      stopAudio();
      stopVideo();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Handle camera selection changes
  useEffect(() => {
    if (selectedCamera) {
      handleStartVideo(selectedCamera);
    } else {
      stopVideo();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedCamera]);

  // Handle microphone selection changes
  useEffect(() => {
    if (selectedMicrophone) {
      handleStartAudio(selectedMicrophone);
    } else {
      stopAudio();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedMicrophone]);

  // Function to start video stream
  const handleStartVideo = async (deviceId: string) => {
    stopVideo(); // Stop any existing video streams
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { deviceId: { exact: deviceId } },
      });
      if (videoRef.current) {
        videoRef.current.srcObject = stream;
      }
      mediaStreamRef.current = stream;
    } catch (error) {
      console.error('Error starting video:', error);
    }
  };

  // Function to stop video stream
  const stopVideo = () => {
    if (mediaStreamRef.current) {
      mediaStreamRef.current.getTracks().forEach(track => track.stop());
      mediaStreamRef.current = null;
    }
    if (videoRef.current) {
      videoRef.current.srcObject = null;
    }
  };

  // Function to start audio analysis
  const handleStartAudio = async (deviceId: string) => {
    stopAudio(); // Stop any existing audio streams

    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: { deviceId: { exact: deviceId } },
      });
      mediaStreamRef.current = stream;

      audioContextRef.current = new (window.AudioContext || (window as any).webkitAudioContext)();
      const source = audioContextRef.current.createMediaStreamSource(stream);

      analyserRef.current = audioContextRef.current.createAnalyser();
      analyserRef.current.fftSize = 256;
      const bufferLength = analyserRef.current.frequencyBinCount;
      dataArrayRef.current = new Uint8Array(bufferLength);

      source.connect(analyserRef.current);

      const analyze = () => {
        if (analyserRef.current && dataArrayRef.current) {
          analyserRef.current.getByteFrequencyData(dataArrayRef.current);
          let sum = 0;
          for (let i = 0; i < dataArrayRef.current.length; i++) {
            sum += dataArrayRef.current[i];
          }
          const avg = sum / dataArrayRef.current.length;
          setAudioLevel(avg);
        }
        animationIdRef.current = requestAnimationFrame(analyze);
      };

      analyze();
    } catch (error) {
      console.error('Error starting audio:', error);
    }
  };

  // Function to stop audio analysis
  const stopAudio = () => {
    if (animationIdRef.current) {
      cancelAnimationFrame(animationIdRef.current);
      animationIdRef.current = null;
    }
    if (audioContextRef.current) {
      audioContextRef.current.close();
      audioContextRef.current = null;
    }
    setAudioLevel(0);
    if (mediaStreamRef.current) {
      mediaStreamRef.current.getTracks().forEach(track => track.stop());
      mediaStreamRef.current = null;
    }
  };

  // detect change in camera type
  useEffect(() => {
    if (selectedCamera) {
      handleStartVideo(selectedCamera);
    } else {
      stopVideo();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedCamera]);

  // detect change in microphone type
  useEffect(() => {
    if (selectedMicrophone) {
      handleStartAudio(selectedMicrophone);
    } else {
      stopAudio();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  },
  [selectedMicrophone]);

  return (
    
<>

        {/* Video Control Section */}
        <div className="p-2 border rounded-lg bg-gray-50 mb-4 max-w-lg m-auto dark:bg-gray-800 dark:border-gray-700"> <div className="mb-4">
              <div className='grid grid-cols-1 md:grid-cols-3 md:gap-2 '>
             
              <div className="col-span-2 mb-4">
              <div className="flex items-center space-x-4 mt-4">
                <CameraPermissionButton />
              <PermissionStatus
                permissionType="camera"
                state={cameraPermissionState}
                className="text-sm text-gray-600"
              /></div>
               <div className="space-y-4 mt-4">
                <div>
                  <select
                    id="cameraSelect"
                    className="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm dark:bg-gray-800 dark:border-gray-700"
                    value={selectedCamera || ''}
                    onChange={e => setSelectedCamera(e.target.value)}
                    
                  >
                    <option value="">-- Select a camera --</option>
                    {videoDevices.map(device => (
                      <option key={device.deviceId} value={device.deviceId}>
                        {device.label || `Camera ${device.deviceId}`}
                      </option>
                    ))}
                  </select>
                </div>
            </div>
            </div> <video
                ref={videoRef}
                autoPlay
                playsInline
                muted
                className="w-full h-auto border rounded-md shadow-sm"
                width="100%"
                height="auto"
              />
              </div>
             
           
          </div>
        </div>

        {/* Audio Control Section */}
        <div className="p-4 border rounded-lg bg-gray-50  max-w-lg m-auto mb-4 dark:bg-gray-800 dark:border-gray-700">
        <div  className='mb-2'>
        <div className="flex items-center space-x-4">
              <MicrophonePermissionButton/>
              <PermissionStatus
                permissionType="microphone"
                state={microphonePermissionState}
                className="text-sm text-gray-600"
              />
            </div>
            </div>
          <div className="space-y-4">
            <div>
                
              <progress
  value={audioLevel}
  max={255}
  className="w-full h-2 bg-gray-200 rounded"
  style={{ appearance: 'none', WebkitAppearance: 'none', MozAppearance: 'none' }}
>
  <style>
    {`
      progress::-webkit-progress-bar {
        background-color: #e5e7eb; /* bg-gray-200 */
        border-radius: 0.375rem; /* rounded */
      }
      progress::-webkit-progress-value {
        background-color: #10b981; /* green-500 */
        border-radius: 0.375rem;
      }
      progress::-moz-progress-bar {
        background-color: #10b981;
        border-radius: 0.375rem;
      }
    `}
  </style>
</progress>

            </div>
              <select
                id="microphoneSelect"
                className="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-green-500 text-sm "
                value={selectedMicrophone || ''}
                onChange={e => setSelectedMicrophone(e.target.value)}
              >
                <option value="">-- Select a microphone --</option>
                {audioDevices.map(device => (
                  <option key={device.deviceId} value={device.deviceId}>
                    {device.label || `Microphone ${device.deviceId}`}
                  </option>
                ))}
              </select>
            </div>
            <div>
             
          </div>
        </div>
        </>
  );
};
