import { faPause, faPlay, faVolumeHigh } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useState, useRef, useEffect, useCallback } from 'react';
import { formatDuration } from './RestrictedAudioPlayer';
import { useExamTranslation } from '../../../i18n';
const AudioPlayer = ({ src, variant = 'repeatable', labelId }) => {
    const [isPlaying, setIsPlaying] = useState(false);
    const [currentTime, setCurrentTime] = useState(0);
    const [duration, setDuration] = useState(0);
    const audioRef = useRef(null);
    const progressBarRef = useRef(null);
    const { t } = useExamTranslation();
    useEffect(() => {
        const audio = audioRef.current;
        if (!audio)
            return;
        const onDurationChange = () => {
            if (audio.duration !== Infinity) {
                setDuration(audio.duration);
                // After the hacky 'seek to infinity', Seek audio back to the start.
                // Also causes seek back to beginning if duration updates for some other reason.
                // But this should not happen in practice once we have the non-infinite duration.
                if (audio.currentTime === audio.duration) {
                    onTimeUpdate(0);
                }
                else {
                    onTimeUpdate();
                }
            }
            else {
                // Hack to force chromium to get the real duration by seeking far beyond the end
                onTimeUpdate(Number.MAX_SAFE_INTEGER);
            }
        };
        const onTime = () => onTimeUpdate();
        const setPlayingFalse = () => setIsPlaying(false);
        const setPlayingTrue = () => setIsPlaying(true);
        audio.addEventListener('loadeddata', onDurationChange);
        audio.addEventListener('loadedmetadata', onDurationChange);
        audio.addEventListener('durationchange', onDurationChange);
        audio.addEventListener('timeupdate', onTime);
        audio.addEventListener('playing', setPlayingTrue);
        audio.addEventListener('pause', setPlayingFalse);
        audio.addEventListener('ended', setPlayingFalse);
        return () => {
            setIsPlaying(false);
            audio.removeEventListener('loadeddata', onDurationChange);
            audio.removeEventListener('loadedmetadata', onDurationChange);
            audio.removeEventListener('durationchange', onDurationChange);
            audio.removeEventListener('timeupdate', onTime);
            audio.removeEventListener('playing', setPlayingTrue);
            audio.removeEventListener('pause', setPlayingFalse);
            audio.removeEventListener('ended', setPlayingFalse);
        };
    }, [src]);
    useEffect(() => {
        var _a, _b;
        if (isPlaying)
            void ((_a = audioRef.current) === null || _a === void 0 ? void 0 : _a.play());
        else
            (_b = audioRef.current) === null || _b === void 0 ? void 0 : _b.pause();
    }, [isPlaying]);
    const togglePlay = () => setIsPlaying(prev => !prev);
    const onSeek = (e) => {
        const t = +e.target.value;
        onTimeUpdate(t);
    };
    const onTimeUpdate = useCallback((seekTime) => {
        if (!audioRef.current)
            return;
        if (seekTime !== undefined)
            audioRef.current.currentTime = seekTime;
        const newTime = audioRef.current.currentTime;
        if (!Number.isFinite(newTime))
            return;
        // for some reason duration is 0 here, so we use the audioRef
        // Ensure duration is not NaN or 0 before division to prevent issues
        const dur = !Number.isFinite(audioRef.current.duration) ? 0 : audioRef.current.duration;
        setCurrentTime(newTime);
        if (progressBarRef.current) {
            progressBarRef.current.style.setProperty('--range-progress', `${dur > 0 ? (newTime / dur) * 100 : 0}%`);
        }
    }, [audioRef, progressBarRef]);
    return (React.createElement("div", { className: `custom-audio-player custom-audio-player--${variant} e-column e-column--narrow`, "aria-describedby": labelId, "data-testid": "audio-player-container" },
        React.createElement("audio", { ref: audioRef, src: src, preload: "metadata", "aria-hidden": "true" }),
        React.createElement("button", { className: `play-button`, onClick: togglePlay, "data-testid": "audio-player-play-pause-button", "aria-label": isPlaying ? t.raw('audio-player.aria.pause') : t.raw('audio-player.aria.play') },
            React.createElement(FontAwesomeIcon, { icon: isPlaying ? faPause : faPlay, className: "icon" })),
        React.createElement("span", { className: `time`, "data-testid": "audio-player-current-time", "aria-hidden": "true" }, formatDuration(currentTime)),
        React.createElement("input", { ref: progressBarRef, type: "range", min: 0, max: Number.isFinite(duration) ? duration : 0, step: 0.01, value: currentTime, onChange: onSeek, "aria-label": t.raw('audio-player.aria.seek-slider-aria-label'), "aria-valuetext": `${formatDuration(currentTime)}/${formatDuration(duration)}`, "data-testid": "audio-player-progress-bar" }),
        React.createElement("span", { className: `time`, "data-testid": "audio-player-duration", "aria-hidden": "true" }, formatDuration(duration)),
        React.createElement(FontAwesomeIcon, { icon: faVolumeHigh, className: `audio-icon`, "aria-hidden": "true" })));
};
export default AudioPlayer;
//# sourceMappingURL=AudioPlayer.js.map