#!/usr/bin/env python3
# -*- coding: utf-8 -*-import tkinter as tk

import tkinter as tk
from tkinter import filedialog, messagebox, ttk
import threading
import pygame
import os
import time

# Custom modules imports
from core.tts_engine import TTSEngine, VOICE_DATA
from core.parser import FileParser
from ui.main_window import MainWindow
from core.messages import get_strings

class FussReaderApp:
    def __init__(self, root):
        self.root = root
        
        # Load translations based on system language
        self.msgs = get_strings()
        
        # Initialize audio mixer
        pygame.mixer.init()
        self.tts = TTSEngine()
        
        # Pass the 'self.msgs' dictionary to MainWindow
        self.ui = MainWindow(self.root, self, self.msgs)
        
        self.is_reading = False
        self.is_paused = False
        self.stop_requested = False

    def load_file(self):
        import subprocess
        import os

        # Zenity command for a clean file selection UI on Linux/GNOME
        cmd = [
            "zenity", "--file-selection", 
            "--title=Seleziona un documento per FUSS Reader",
            "--filename=" + os.path.expanduser("~") + "/", # Parte dalla Home
            "--file-filter=Documenti supportati | *.pdf *.txt *.epub *.odt *.docx",
            "--file-filter=Tutti i file | *"
        ]

        try:
            # Execute Zenity process
            process = subprocess.run(cmd, capture_output=True, text=True)
            
            # If user clicks "Cancel", Zenity exits with return code 1
            if process.returncode != 0:
                return

            file_path = process.stdout.strip()

            if file_path and os.path.exists(file_path):
                # Use our custom parser to extract text from various formats
                testo = FileParser.extract_text(file_path)
                
                # Update the text area in the UI
                self.ui.text_area.delete("1.0", "end")
                self.ui.text_area.insert("1.0", testo)
                
                # Reset cursor and focus back to the main window
                self.ui.text_area.mark_set("insert", "1.0")
                self.ui.text_area.see("1.0")
                self.ui.text_area.focus_set()

        except Exception as e:
            # Fallback to standard Tkinter filedialog if Zenity is not available
            from tkinter import filedialog
            file_path = filedialog.askopenfilename(initialdir="~")
            if file_path:
                testo = FileParser.extract_text(file_path)
                self.ui.text_area.delete("1.0", "end")
                self.ui.text_area.insert("1.0", testo)

    def toggle_pause(self):
        if not self.is_reading:
            return
            
        if not self.is_paused:
            pygame.mixer.music.pause()
            self.is_paused = True
            self.ui.pause_btn.config(text=self.msgs["btn_resume"], bg="#17a2b8")
        else:
            pygame.mixer.music.unpause()
            self.is_paused = False
            self.ui.pause_btn.config(text=self.msgs["btn_pause"], bg="#ff9800")

    def stop_reading(self):
        self.stop_requested = True
        self.is_paused = False
        pygame.mixer.music.stop()
        self.ui.text_area.tag_remove("highlight", "1.0", "end")

    def clear_all(self):
        """Stops the audio playback and resets highlighting."""
        self.stop_reading()

        if messagebox.askyesno(self.msgs["confirm_clear_title"], self.msgs["confirm_clear_msg"]):
            self.ui.text_area.delete("1.0", "end")

    def start_reading(self):
        # If already reading, the button acts as "Resume" if it was paused
        if self.is_reading:
            if self.is_paused:
                self.toggle_pause()
            return

        # Get the current cursor position
        cursor_pos = self.ui.text_area.index(tk.INSERT)
        
        # Smart check: if cursor is at the very end or area is empty, 
        testo_rimanente = self.ui.text_area.get(cursor_pos, "end-1c").strip()
        
        if not testo_rimanente:
            # If nothing to read after cursor, check if there is any text at all
            testo_totale = self.ui.text_area.get("1.0", "end-1c").strip()
            if not testo_totale:
                # Show warning: "Place the cursor where you want to start..."
                messagebox.showinfo("FUSS Reader", self.msgs["msg_empty"])
                return
            else:
                # If text exists but cursor is at the end, restart from the beginning
                cursor_pos = "1.0"
                self.ui.text_area.mark_set("insert", "1.0")

        # Reading startup
        self.is_reading = True
        self.stop_requested = False
        
        # Disable play button during reading to prevent multiple thread activations
        self.ui.play_btn.config(state="disabled")
        
        threading.Thread(target=self.reading_loop, args=(cursor_pos,), daemon=True).start()

    def reading_loop(self, start_idx):
        testo_da_leggere = self.ui.text_area.get(start_idx, "end-1c")
        righe = testo_da_leggere.splitlines()
        offset = len(self.ui.text_area.get("1.0", start_idx))
        v_id = self.ui.voice_var.get()

        for riga in righe:
            if self.stop_requested: break
            if not riga.strip():
                offset += len(riga) + 1
                continue

            # RETRIEVE PARAMETERS
            v_id = self.ui.voice_var.get()
            v_info = VOICE_DATA[v_id]  # Recuperiamo l'oggetto con file e rate
            current_speed = self.ui.speed_scale.get() # Recuperiamo la velocità dallo slider

            # ENGINE CALL (Passing voice info and speed)
            audio_wav, durata_ms = self.tts.generate_speech(riga, v_info, current_speed)
            
            if audio_wav:
                # Store temporary wave file for playback
                with open("/tmp/reader.wav", "wb") as f: f.write(audio_wav)
                pygame.mixer.music.load("/tmp/reader.wav")
                pygame.mixer.music.play()

                # Start word-by-word highlighting
                self.karaoke_word_by_word(riga, durata_ms, offset)
                
                # Wait for audio to finish while handling Pause/Stop
                while pygame.mixer.music.get_busy() or self.is_paused:
                    if self.stop_requested: break
                    time.sleep(0.05)

            offset += len(riga) + 1
        
        # Reset UI state once reading is finished or stopped
        self.is_reading = False
        self.root.after(0, lambda: self.ui.play_btn.config(state="normal"))

    def karaoke_word_by_word(self, riga, durata_totale, offset_globale):
        """Synchronizes the yellow highlight with the spoken words."""
        parole = riga.split()
        ms_per_char = durata_totale / len(riga) if len(riga) > 0 else 0
        pos_nella_riga = 0

        for parola in parole:
            if self.stop_requested: break
            # Wait loop if paused
            while self.is_paused:
                if self.stop_requested: break
                time.sleep(0.1)

            inizio_parola = riga.find(parola, pos_nella_riga)
            s = f"1.0 + {offset_globale + inizio_parola} chars"
            e = f"1.0 + {offset_globale + inizio_parola + len(parola)} chars"
            
            # Update UI from thread
            self.root.after(0, lambda start=s, end=e: self.apply_highlight(start, end))
            
            # Wait time proportional to word length
            time.sleep(((len(parola) + 1) * ms_per_char) / 1000)
            pos_nella_riga = inizio_parola + len(parola)

    def apply_highlight(self, s, e):
        """Applies yellow background to the current word and ensures it's visible."""
        self.ui.text_area.tag_remove("highlight", "1.0", "end")
        self.ui.text_area.tag_add("highlight", s, e)
        self.ui.text_area.see(s)

    def paste_text(self):
        """Pastes text from clipboard and forces cursor to the beginning."""
        try:
            testo_appunti = self.root.clipboard_get()
            if testo_appunti:
                # If text is selected, delete it first (standard paste behavior)
                try:
                    self.ui.text_area.delete("sel.first", "sel.last")
                except:
                    pass
                
                # If the default welcome message is present, clear the whole area
                content = self.ui.text_area.get("1.0", "end-1c")
                if "Benvenuto" in content and len(content) < 100:
                    self.ui.text_area.delete("1.0", "end")

                # Insert the text at current cursor position
                self.ui.text_area.insert(tk.INSERT, testo_appunti)
                
                # COMPLETE SOLUTION: Move cursor back to the beginning for immediate reading
                self.ui.text_area.mark_set("insert", "1.0")
                self.ui.text_area.see("1.0")
                self.ui.text_area.focus_set()
                
            # Return "break" to prevent standard Tkinter paste (avoids duplicates)
            return "break"
        except tk.TclError:
            return "break"
            
    def quit_app(self):
        """Clean exit stopping playback and destroying the main window."""
        self.stop_reading()
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = FussReaderApp(root)
    root.mainloop()
