"use strict";
/**
 * useVoiceInput Hook - Advanced voice recognition with real-time feedback
 * Features: Continuous listening, confidence scoring, multi-language support
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAdvancedVoiceInput = exports.useVoiceInput = void 0;
const react_1 = require("react");
// Check for browser support
const getSpeechRecognition = () => {
    if (typeof window === 'undefined')
        return null;
    return (window.SpeechRecognition ||
        window.webkitSpeechRecognition ||
        window.mozSpeechRecognition ||
        window.msSpeechRecognition);
};
const useVoiceInput = ({ enabled = true, continuous = false, interimResults = true, language = 'en-US', maxAlternatives = 3, onResult, onError, onStart, onEnd, autoRestart = false, silenceTimeout = 3000, confidenceThreshold = 0.5 } = {}) => {
    const [isListening, setIsListening] = (0, react_1.useState)(false);
    const [transcript, setTranscript] = (0, react_1.useState)('');
    const [interimTranscript, setInterimTranscript] = (0, react_1.useState)('');
    const [confidence, setConfidence] = (0, react_1.useState)(0);
    const [error, setError] = (0, react_1.useState)(null);
    const [alternatives, setAlternatives] = (0, react_1.useState)([]);
    const recognitionRef = (0, react_1.useRef)(null);
    const isListeningRef = (0, react_1.useRef)(false);
    const silenceTimeoutRef = (0, react_1.useRef)();
    const restartTimeoutRef = (0, react_1.useRef)();
    const SpeechRecognition = getSpeechRecognition();
    const isSupported = Boolean(SpeechRecognition);
    // Initialize speech recognition
    (0, react_1.useEffect)(() => {
        if (!isSupported || !enabled)
            return;
        const recognition = new SpeechRecognition();
        // Configure recognition
        recognition.continuous = continuous;
        recognition.interimResults = interimResults;
        recognition.lang = language;
        recognition.maxAlternatives = maxAlternatives;
        // Event handlers
        recognition.onstart = () => {
            console.log('🎤 Voice recognition started');
            setIsListening(true);
            setError(null);
            onStart?.();
        };
        recognition.onend = () => {
            console.log('🎤 Voice recognition ended');
            setIsListening(false);
            isListeningRef.current = false;
            onEnd?.();
            // Auto-restart if enabled and still supposed to be listening
            if (autoRestart && isListeningRef.current) {
                restartTimeoutRef.current = setTimeout(() => {
                    if (isListeningRef.current) {
                        try {
                            recognition.start();
                        }
                        catch (err) {
                            console.error('Failed to restart recognition:', err);
                        }
                    }
                }, 100);
            }
        };
        recognition.onresult = (event) => {
            let finalTranscript = '';
            let interimText = '';
            let maxConfidence = 0;
            let bestAlternatives = [];
            // Process all results
            for (let i = event.resultIndex; i < event.results.length; i++) {
                const result = event.results[i];
                const resultTranscript = result[0].transcript;
                const resultConfidence = result[0].confidence || 0;
                if (result.isFinal) {
                    finalTranscript += resultTranscript;
                    maxConfidence = Math.max(maxConfidence, resultConfidence);
                    // Collect alternatives for final results
                    const resultAlternatives = [];
                    for (let j = 0; j < Math.min(result.length, maxAlternatives); j++) {
                        resultAlternatives.push({
                            transcript: result[j].transcript,
                            confidence: result[j].confidence || 0
                        });
                    }
                    bestAlternatives = resultAlternatives;
                }
                else {
                    interimText += resultTranscript;
                }
            }
            // Update state
            if (finalTranscript) {
                setTranscript(prev => prev + finalTranscript);
                setConfidence(maxConfidence);
                setAlternatives(bestAlternatives);
                // Trigger callback if confidence meets threshold
                if (maxConfidence >= confidenceThreshold) {
                    onResult?.(finalTranscript, maxConfidence);
                }
                // Reset silence timeout
                if (silenceTimeoutRef.current) {
                    clearTimeout(silenceTimeoutRef.current);
                }
            }
            if (interimText) {
                setInterimTranscript(interimText);
            }
            // Set silence timeout for continuous mode
            if (continuous && finalTranscript) {
                silenceTimeoutRef.current = setTimeout(() => {
                    if (isListeningRef.current) {
                        stopListening();
                    }
                }, silenceTimeout);
            }
        };
        recognition.onerror = (event) => {
            console.error('🎤 Voice recognition error:', event.error);
            const errorMessage = getErrorMessage(event.error);
            setError(errorMessage);
            setIsListening(false);
            isListeningRef.current = false;
            onError?.({
                error: event.error,
                message: errorMessage
            });
            // Don't auto-restart on certain errors
            const nonRestartableErrors = ['not-allowed', 'service-not-allowed', 'network'];
            if (autoRestart && !nonRestartableErrors.includes(event.error)) {
                restartTimeoutRef.current = setTimeout(() => {
                    if (isListeningRef.current) {
                        try {
                            recognition.start();
                        }
                        catch (err) {
                            console.error('Failed to restart after error:', err);
                        }
                    }
                }, 1000);
            }
        };
        recognition.onaudiostart = () => {
            console.log('🎤 Audio capture started');
        };
        recognition.onaudioend = () => {
            console.log('🎤 Audio capture ended');
        };
        recognition.onsoundstart = () => {
            console.log('🎤 Sound detected');
        };
        recognition.onsoundend = () => {
            console.log('🎤 Sound ended');
        };
        recognition.onspeechstart = () => {
            console.log('🎤 Speech detected');
            // Clear interim transcript when speech starts
            setInterimTranscript('');
        };
        recognition.onspeechend = () => {
            console.log('🎤 Speech ended');
        };
        recognition.onnomatch = () => {
            console.log('🎤 No speech recognized');
            setError('No speech was recognized');
        };
        recognitionRef.current = recognition;
        return () => {
            if (recognitionRef.current) {
                recognitionRef.current.abort();
            }
            if (silenceTimeoutRef.current) {
                clearTimeout(silenceTimeoutRef.current);
            }
            if (restartTimeoutRef.current) {
                clearTimeout(restartTimeoutRef.current);
            }
        };
    }, [
        isSupported,
        enabled,
        continuous,
        interimResults,
        language,
        maxAlternatives,
        autoRestart,
        silenceTimeout,
        confidenceThreshold,
        onResult,
        onError,
        onStart,
        onEnd
    ]);
    // Start listening
    const startListening = (0, react_1.useCallback)(() => {
        if (!isSupported || !enabled || !recognitionRef.current) {
            setError('Speech recognition is not supported or enabled');
            return;
        }
        if (isListeningRef.current) {
            console.log('🎤 Already listening');
            return;
        }
        try {
            // Reset state
            setError(null);
            setInterimTranscript('');
            // Start recognition
            isListeningRef.current = true;
            recognitionRef.current.start();
        }
        catch (err) {
            console.error('Failed to start voice recognition:', err);
            setError('Failed to start voice recognition');
            isListeningRef.current = false;
        }
    }, [isSupported, enabled]);
    // Stop listening
    const stopListening = (0, react_1.useCallback)(() => {
        if (!recognitionRef.current)
            return;
        try {
            isListeningRef.current = false;
            recognitionRef.current.stop();
            // Clear timeouts
            if (silenceTimeoutRef.current) {
                clearTimeout(silenceTimeoutRef.current);
            }
            if (restartTimeoutRef.current) {
                clearTimeout(restartTimeoutRef.current);
            }
        }
        catch (err) {
            console.error('Failed to stop voice recognition:', err);
        }
    }, []);
    // Reset transcript
    const resetTranscript = (0, react_1.useCallback)(() => {
        setTranscript('');
        setInterimTranscript('');
        setConfidence(0);
        setAlternatives([]);
        setError(null);
    }, []);
    // Cleanup on unmount
    (0, react_1.useEffect)(() => {
        return () => {
            if (recognitionRef.current) {
                recognitionRef.current.abort();
            }
            if (silenceTimeoutRef.current) {
                clearTimeout(silenceTimeoutRef.current);
            }
            if (restartTimeoutRef.current) {
                clearTimeout(restartTimeoutRef.current);
            }
        };
    }, []);
    return {
        isListening,
        transcript,
        interimTranscript,
        confidence,
        isSupported,
        error,
        startListening,
        stopListening,
        resetTranscript,
        alternatives
    };
};
exports.useVoiceInput = useVoiceInput;
// Helper function to get user-friendly error messages
function getErrorMessage(error) {
    const errorMessages = {
        'no-speech': 'No speech was detected. Please try again.',
        'aborted': 'Speech recognition was aborted.',
        'audio-capture': 'Audio capture failed. Please check your microphone.',
        'network': 'Network error occurred. Please check your connection.',
        'not-allowed': 'Microphone access was denied. Please allow microphone access.',
        'service-not-allowed': 'Speech recognition service is not allowed.',
        'bad-grammar': 'Speech recognition grammar error.',
        'language-not-supported': 'The specified language is not supported.'
    };
    return errorMessages[error] || `Speech recognition error: ${error}`;
}
// Enhanced hook with additional features
const useAdvancedVoiceInput = (options) => {
    const baseHook = (0, exports.useVoiceInput)(options);
    const [isWakeWordActive, setIsWakeWordActive] = (0, react_1.useState)(false);
    const [detectedCommands, setDetectedCommands] = (0, react_1.useState)([]);
    // Wake word detection
    (0, react_1.useEffect)(() => {
        if (options.wakeWord && baseHook.transcript.toLowerCase().includes(options.wakeWord.toLowerCase())) {
            setIsWakeWordActive(true);
            console.log(`🎤 Wake word "${options.wakeWord}" detected`);
        }
    }, [baseHook.transcript, options.wakeWord]);
    // Command pattern matching
    (0, react_1.useEffect)(() => {
        if (options.commandPatterns && baseHook.transcript) {
            const newCommands = [];
            options.commandPatterns.forEach(({ pattern, action }) => {
                const matches = baseHook.transcript.match(pattern);
                if (matches) {
                    newCommands.push(matches[0]);
                    action(matches);
                }
            });
            if (newCommands.length > 0) {
                setDetectedCommands(prev => [...prev, ...newCommands]);
            }
        }
    }, [baseHook.transcript, options.commandPatterns]);
    return {
        ...baseHook,
        isWakeWordActive,
        detectedCommands,
        clearCommands: () => setDetectedCommands([]),
        resetWakeWord: () => setIsWakeWordActive(false)
    };
};
exports.useAdvancedVoiceInput = useAdvancedVoiceInput;
exports.default = exports.useVoiceInput;
//# sourceMappingURL=useVoiceInput.js.map