import { Component, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core'; import { FindwordService } from '../findword/findword.service'; import { Router } from '@angular/router'; import { HeaderComponent } from '../shared/header/header.component'; import { ButtonComponent } from '../shared/button/button.component'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-findword', templateUrl: './findword.component.html', styleUrl: './findword.component.css', standalone: true, imports: [ButtonComponent, CommonModule, FormsModule, HeaderComponent] }) export class FindwordComponent { @ViewChild('audioPlayer', { static: false }) audioPlayer?: ElementRef; @ViewChild('audioPlayer') audioRef!: ElementRef; step: number = 1; progress: number = 0; audioUrl: string | null = null; userInput: string = ''; validationMessage: string = ''; isCorrect: boolean = false; isLoading: boolean = false; attemptsLeft: number = 3; correctWord: string | null = null; isGenerateDisabled: boolean = false; wordMeaning: string | null = null; wordSentence: string | null = null; showMeaning: boolean = false; showSentence: boolean = false; isPopupVisible: boolean = false; popupMessage: string = ''; audioFinished: boolean = false; canSubmit: boolean = false; isPlaying: boolean = false; currentTimeDisplay = '0:00'; durationDisplay = '0:00'; constructor( private findwordService: FindwordService, private cd: ChangeDetectorRef, private router: Router ) { } fetchAudio() { this.isLoading = true; this.correctWord = null; this.attemptsLeft = 3; this.validationMessage = ''; this.userInput = ''; this.isGenerateDisabled = true; this.wordMeaning = null; this.wordSentence = null; this.showMeaning = true; this.showSentence = true; this.audioFinished = false; this.canSubmit = false; console.log("🎤 Fetching new vocabulary..."); this.findwordService.fetchAudio().subscribe((response: any) => { if (!response || !response.audio_file_path || !response.word) { console.error("❌ Invalid response from backend:", response); return; } this.correctWord = response.word.trim(); this.wordMeaning = response.meaning; this.wordSentence = response.sentence; console.log("✅ Correct Word Set:", this.correctWord); this.audioUrl = this.findwordService.buildAssetUrl(response.audio_file_path); this.cd.detectChanges(); setTimeout(() => { if (this.audioPlayer && this.audioPlayer.nativeElement) { console.log("🔄 Loading new audio..."); this.audioPlayer.nativeElement.load(); this.audioPlayer.nativeElement.onended = () => { console.log("🔊 Audio finished playing"); this.audioFinished = true; }; } else { console.error("❌ Audio player not found!"); } }, 500); }, error => { console.error('❌ Error fetching audio:', error); this.isLoading = false; }); } onInputChange(): void { this.canSubmit = this.userInput.trim().length > 0; } startGame(): void { this.resetStep2State(); this.step = 2; this.progress = 0; } getMeaning() { if (this.wordMeaning) { this.popupMessage = `Meaning: ${this.wordMeaning}`; } else { this.popupMessage = 'Meaning not available for this word.'; } this.isPopupVisible = true; } getSentence() { if (this.wordSentence) { this.popupMessage = `Example Sentence: ${this.wordSentence}`; } else { this.popupMessage = 'Example sentence not available for this word.'; } this.isPopupVisible = true; } validateWord() { if (this.attemptsLeft <= 0) { this.showMeaning = true; this.showSentence = true; return; } console.log(`📝 Validating answer: ${this.userInput} (Attempts left: ${this.attemptsLeft})`); if (!this.correctWord) { console.error("❌ Error: No correct word set for validation!"); this.validationMessage = 'Error validating word: Missing correct word.'; this.showMeaning = true; this.showSentence = true; return; } const requestData = { user_input: this.userInput.trim(), correct_word: this.correctWord.trim().replace('.', '') }; console.log("📤 Sending validation request:", requestData); this.findwordService.validateWord(this.userInput, this.correctWord).subscribe(response => { console.log("📥 Validation Response:", response); if (response.status === 'success') { this.validationMessage = "✅ Correct!"; this.isCorrect = true; this.ui.pulseOk = true; setTimeout(() => (this.ui.pulseOk = false), 1200); this.attemptsLeft = 0; this.popupMessage = this.validationMessage; this.isGenerateDisabled = true; } else { this.attemptsLeft--; if (this.attemptsLeft === 0) { this.validationMessage = `❌ Incorrect! The correct word was '${this.correctWord}'.`; this.correctWord = response.correct_word; this.isGenerateDisabled = true; this.showMeaning = true; this.showSentence = true; } else { this.validationMessage = `❌ Incorrect! You have ${this.attemptsLeft} attempt(s) left.`; } this.isCorrect = false; this.ui.shake = true; setTimeout(() => (this.ui.shake = false), 400); } }, error => { console.error("❌ Validation API Error:", error); this.validationMessage = 'Error validating word: API failed.'; }); } onAudioReady() { console.log("🎧 Audio is ready, trying to play..."); if (this.audioPlayer) { this.audioPlayer.nativeElement.play().then(() => { console.log("✅ Audio played successfully."); }).catch((error: any) => { console.error("❌ Play failed:", error); }); } } pauseAudio() { if (this.audioPlayer?.nativeElement) { this.audioPlayer.nativeElement.pause(); } } playAudio() { if (this.audioPlayer?.nativeElement) { this.audioPlayer.nativeElement.play(); } console.log("🎵 Play button clicked. Trying to play audio:", this.audioUrl); if (this.audioPlayer && this.audioPlayer.nativeElement) { this.audioPlayer.nativeElement.play().then(() => { console.log("✅ Audio played successfully."); }).catch((error: any) => { console.error("❌ Manual play failed:", error); }); } else { console.error("❌ Audio player not found!"); } } nextQuestion() { this.isGenerateDisabled = false; this.audioUrl = null; this.userInput = ''; this.validationMessage = ''; this.attemptsLeft = 3; this.correctWord = null; this.showMeaning = false; this.showSentence = false; this.isCorrect = false; this.isLoading = false; this.fetchAudio(); } goToHome() { this.router.navigate(['/home']); } goBack(): void { const audio = this.audioRef?.nativeElement; if (audio) { try { audio.pause(); } catch { } } this.step = 1; } showMeaningPanel() { if (this.wordMeaning) { this.popupMessage = `📖 Meaning: ${this.wordMeaning}`; } else { this.popupMessage = 'Meaning not available for this word.'; } this.isPopupVisible = true; this.ui.showMeaning = true; this.ui.showExample = false; this.ui.meaningText = (this as any).meaningText || (this as any).meaning || ''; } showSentencePanel() { if (this.wordSentence) { this.popupMessage = `✍ Example Sentence: ${this.wordSentence}`; } else { this.popupMessage = 'Example sentence not available for this word.'; } this.isPopupVisible = true; this.ui.showExample = true; this.ui.showMeaning = false; this.ui.exampleText = (this as any).exampleText || (this as any).sentence || (this as any).exampleSentence || ''; } closePopup() { console.log("❌ Closing popup..."); this.isPopupVisible = false; } get isMeaningButtonDisabled(): boolean { return !(this.isCorrect || this.attemptsLeft <= 2); } get isExampleButtonDisabled(): boolean { return !(this.isCorrect || this.attemptsLeft === 0); } bars = Array.from({ length: 12 }); togglePlayback(): void { const audio = this.audioRef?.nativeElement; if (!audio || !this.audioUrl) { return; } if (audio.paused) { audio.play().then(() => { this.isPlaying = true; }).catch(() => { this.isPlaying = false; }); } else { audio.pause(); this.isPlaying = false; } } onLoadedMeta(): void { const audio = this.audioRef?.nativeElement; if (!audio) { return; } this.durationDisplay = this.formatTime(audio.duration); this.currentTimeDisplay = '0:00'; this.progress = 0; this.isPlaying = false; if (typeof this.audioFinished !== 'undefined') { this.audioFinished = false; } } onTimeUpdate(): void { const audio = this.audioRef?.nativeElement; if (!audio) { return; } const current = isFinite(audio.currentTime) ? audio.currentTime : 0; const dur = isFinite(audio.duration) ? audio.duration : 0.00001; this.currentTimeDisplay = this.formatTime(current); this.progress = Math.min(100, (current / dur) * 100); } onAudioEnded(): void { this.isPlaying = false; this.progress = 100; if (typeof this.audioFinished !== 'undefined') { this.audioFinished = true; } } private formatTime(sec: number): string { if (!isFinite(sec)) { return '0:00'; } const m = Math.floor(sec / 60); const s = Math.floor(sec % 60); return `${m}:${s.toString().padStart(2, '0')}`; } private resetPlayerUI(): void { this.isPlaying = false; this.progress = 0; this.currentTimeDisplay = '0:00'; this.durationDisplay = '0:00'; } ui = { pulseOk: false, shake: false, showMeaning: false, showExample: false, meaningText: '', exampleText: '' }; private resetStep2State(): void { const audio = this.audioRef?.nativeElement; if (audio) { try { audio.pause(); } catch { } audio.currentTime = 0; } this.audioUrl = null; this.isPlaying = false; this.progress = 0; this.currentTimeDisplay = '0:00'; this.durationDisplay = '0:00'; this.userInput = ''; this.validationMessage = ''; this.isCorrect = false; this.attemptsLeft = 3; this.canSubmit = false; this.audioFinished = false; this.correctWord = null; this.wordMeaning = null; this.wordSentence = null; this.isGenerateDisabled = false; this.isLoading = false; this.showMeaning = false; this.showSentence = false; if (this.ui) { this.ui.pulseOk = false; this.ui.shake = false; this.ui.showMeaning = false; this.ui.showExample = false; this.ui.meaningText = ''; this.ui.exampleText = ''; } this.isPopupVisible = false; this.popupMessage = ''; } closeToStart(): void { const audio = this.audioRef?.nativeElement; if (audio) { try { audio.pause(); } catch { } audio.currentTime = 0; } this.isPlaying = false; this.audioUrl = null; this.userInput = ''; this.validationMessage = ''; this.isCorrect = false; this.attemptsLeft = 3; this.canSubmit = false; this.audioFinished = false; this.isGenerateDisabled = false; this.isLoading = false; this.showMeaning = false; this.showSentence = false; this.isPopupVisible = false; this.popupMessage = ''; this.step = 1; } }