'use client' import { useState, useCallback, useRef, useEffect } from 'react' import { Language, SlideId } from '../types' import { PresenterState } from '../presenter/types' import { PRESENTER_SCRIPT } from '../presenter/presenter-script' import { SLIDE_ORDER } from './useSlideNavigation' interface UsePresenterModeConfig { goToSlide: (index: number) => void currentSlide: number totalSlides: number language: Language } interface UsePresenterModeReturn { state: PresenterState currentParagraph: number start: () => void stop: () => void pause: () => void resume: () => void skipSlide: () => void toggle: () => void displayText: string progress: number } export function usePresenterMode({ goToSlide, currentSlide, totalSlides, language, }: UsePresenterModeConfig): UsePresenterModeReturn { const [state, setState] = useState('idle') const [currentParagraph, setCurrentParagraph] = useState(0) const [displayText, setDisplayText] = useState('') const timerRef = useRef(null) const slideIndexRef = useRef(currentSlide) const paragraphIndexRef = useRef(0) const stateRef = useRef('idle') // Keep refs in sync useEffect(() => { slideIndexRef.current = currentSlide }, [currentSlide]) useEffect(() => { stateRef.current = state }, [state]) const clearTimer = useCallback(() => { if (timerRef.current) { clearTimeout(timerRef.current) timerRef.current = null } }, []) const getScriptForIndex = useCallback((index: number) => { const slideId = SLIDE_ORDER[index] return PRESENTER_SCRIPT.find(s => s.slideId === slideId) }, []) const showParagraph = useCallback((slideIdx: number, paraIdx: number) => { const script = getScriptForIndex(slideIdx) if (!script || paraIdx >= script.paragraphs.length) return null const para = script.paragraphs[paraIdx] const text = language === 'de' ? para.text_de : para.text_en setDisplayText(text) setCurrentParagraph(paraIdx) paragraphIndexRef.current = paraIdx return para }, [language, getScriptForIndex]) const advancePresentation = useCallback(() => { if (stateRef.current !== 'presenting') return const slideIdx = slideIndexRef.current const script = getScriptForIndex(slideIdx) if (!script) { // No script for this slide, advance to next if (slideIdx < totalSlides - 1) { goToSlide(slideIdx + 1) paragraphIndexRef.current = 0 // Schedule next after slide transition timerRef.current = setTimeout(() => advancePresentation(), 2000) } else { setState('idle') setDisplayText('') } return } const nextPara = paragraphIndexRef.current + 1 if (nextPara < script.paragraphs.length) { // Show next paragraph const para = showParagraph(slideIdx, nextPara) if (para) { // Calculate display time: ~150ms per word + pause const wordCount = (language === 'de' ? para.text_de : para.text_en).split(/\s+/).length const readingTime = Math.max(wordCount * 150, 2000) timerRef.current = setTimeout(() => advancePresentation(), readingTime + para.pause_after) } } else { // All paragraphs done for this slide // Show transition hint briefly if (script.transition_hint_de || script.transition_hint_en) { const hint = language === 'de' ? (script.transition_hint_de || '') : (script.transition_hint_en || '') setDisplayText(hint) } // Move to next slide if (slideIdx < totalSlides - 1) { timerRef.current = setTimeout(() => { if (stateRef.current !== 'presenting') return goToSlide(slideIdx + 1) paragraphIndexRef.current = -1 // Will be incremented to 0 timerRef.current = setTimeout(() => { if (stateRef.current !== 'presenting') return const nextScript = getScriptForIndex(slideIdx + 1) if (nextScript && nextScript.paragraphs.length > 0) { const para = showParagraph(slideIdx + 1, 0) if (para) { const wordCount = (language === 'de' ? para.text_de : para.text_en).split(/\s+/).length const readingTime = Math.max(wordCount * 150, 2000) timerRef.current = setTimeout(() => advancePresentation(), readingTime + para.pause_after) } } else { advancePresentation() } }, 1500) }, 2000) } else { // Last slide — done timerRef.current = setTimeout(() => { setState('idle') setDisplayText('') }, 3000) } } }, [language, totalSlides, goToSlide, getScriptForIndex, showParagraph]) const start = useCallback(() => { clearTimer() setState('presenting') const slideIdx = slideIndexRef.current const script = getScriptForIndex(slideIdx) if (script && script.paragraphs.length > 0) { const para = showParagraph(slideIdx, 0) if (para) { const wordCount = (language === 'de' ? para.text_de : para.text_en).split(/\s+/).length const readingTime = Math.max(wordCount * 150, 2000) timerRef.current = setTimeout(() => advancePresentation(), readingTime + para.pause_after) } } else { // No script, advance immediately timerRef.current = setTimeout(() => advancePresentation(), 1000) } }, [clearTimer, language, getScriptForIndex, showParagraph, advancePresentation]) const stop = useCallback(() => { clearTimer() setState('idle') setDisplayText('') setCurrentParagraph(0) paragraphIndexRef.current = 0 }, [clearTimer]) const pause = useCallback(() => { clearTimer() setState('paused') }, [clearTimer]) const resume = useCallback(() => { setState('resuming') // Brief pause before continuing timerRef.current = setTimeout(() => { setState('presenting') // Continue from where we left off advancePresentation() }, 2000) }, [advancePresentation]) const skipSlide = useCallback(() => { clearTimer() const nextIdx = slideIndexRef.current + 1 if (nextIdx < totalSlides) { goToSlide(nextIdx) paragraphIndexRef.current = -1 if (stateRef.current === 'presenting') { timerRef.current = setTimeout(() => { const script = getScriptForIndex(nextIdx) if (script && script.paragraphs.length > 0) { const para = showParagraph(nextIdx, 0) if (para) { const wordCount = (language === 'de' ? para.text_de : para.text_en).split(/\s+/).length const readingTime = Math.max(wordCount * 150, 2000) timerRef.current = setTimeout(() => advancePresentation(), readingTime + para.pause_after) } } }, 1500) } } }, [clearTimer, totalSlides, goToSlide, language, getScriptForIndex, showParagraph, advancePresentation]) const toggle = useCallback(() => { if (stateRef.current === 'idle') { start() } else { stop() } }, [start, stop]) // Calculate overall progress const progress = (() => { if (state === 'idle') return 0 const totalScripts = PRESENTER_SCRIPT.length const currentScriptIdx = PRESENTER_SCRIPT.findIndex(s => s.slideId === SLIDE_ORDER[currentSlide]) if (currentScriptIdx < 0) return (currentSlide / totalSlides) * 100 const script = PRESENTER_SCRIPT[currentScriptIdx] const slideProgress = script.paragraphs.length > 0 ? currentParagraph / script.paragraphs.length : 0 return ((currentScriptIdx + slideProgress) / totalScripts) * 100 })() // Cleanup on unmount useEffect(() => { return () => clearTimer() }, [clearTimer]) return { state, currentParagraph, start, stop, pause, resume, skipSlide, toggle, displayText, progress, } }