#!/home/pali112/venv/bin/python3

from vosk import Model, KaldiRecognizer
import sounddevice as sd
import json
import pyperclip  # Biblioteka do obsługi schowka
import pyautogui
import sys
import tkinter as tk
from threading import Thread
from pathlib import Path
from pynput import keyboard # Biblioteka do globalnych skrótów

SCRIPT_DIR = Path(__file__).parent
# Ścieżka do modelu
model_path = str(SCRIPT_DIR  / "./vosk-model-small-pl-0.22")
model = Model(model_path)
recognizer = KaldiRecognizer(model, 16000)

listening = False  # Flaga stanu nasłuchiwania
emacs_mode = False  # Flaga trybu Emacs
root = None # Zmienna globalna dla okna głównego

# Funkcja obsługi danych audio
def callback(indata, frames, time, status):
    if status:
        print(f"Status: {status}", file=sys.stderr)
    # Konwersja danych na `bytes`
    data = bytes(indata)
    if recognizer.AcceptWaveform(data):
        result = json.loads(recognizer.Result())
        text = result.get("text", "")
        if text:
            print(f"Rozpoznano: {text}")
            insert_text_with_clipboard(text)

# Funkcja kopiowania do schowka i wklejania
def insert_text_with_clipboard(text):
    try:
        pyperclip.copy(text)  # Kopiowanie tekstu do schowka
        if emacs_mode:
            pyautogui.hotkey('shift', 'insert')  # Wklejanie w trybie Emacs
        else:
            pyautogui.hotkey('ctrl', 'v')  # Standardowe wklejanie
        pyautogui.press('space')  # Dodanie spacji (opcjonalne)
    except Exception as e:
        print(f"Błąd podczas wklejania tekstu: {e}", file=sys.stderr)

# Funkcja nasłuchiwania i rozpoznawania mowy
def listen_and_type():
    global listening
    print("Słucham... (naciśnij Stop, aby zatrzymać)")
    try:
        with sd.RawInputStream(samplerate=16000, blocksize=8000, dtype='int16',
                               channels=1, callback=callback):
            while listening:
                pass  # Nasłuchiwanie trwa w pętli
    except Exception as e:
        print(f"Błąd podczas nasłuchiwania: {e}", file=sys.stderr)

# Funkcje sterujące GUI
def toggle_listening():
    global listening
    if listening:
        listening = False
        update_button_state()
        print("Nasłuchiwanie zatrzymane.")
    else:
        listening = True
        update_button_state()
        thread = Thread(target=listen_and_type)
        thread.daemon = True
        thread.start()

def toggle_emacs_mode():
    global emacs_mode
    emacs_mode = not emacs_mode
    update_emacs_button_state()
    mode = "Emacs" if emacs_mode else "Standard"
    print(f"Tryb wklejania: {mode}")

# Aktualizacja stanu przycisków
def update_button_state():
    # Używamy root.after, aby zapewnić bezpieczeństwo wątków przy zmianie GUI z innego wątku (hotkey)
    if root:
        if listening:
            root.after(0, lambda: toggle_button.config(text="Stop", bg="red", fg="white"))
        else:
            root.after(0, lambda: toggle_button.config(text="Start", bg="lightgrey", fg="black"))

def update_emacs_button_state():
    if emacs_mode:
        emacs_button.config(text="Tryb: Emacs", bg="blue", fg="white")
    else:
        emacs_button.config(text="Tryb: Standard", bg="lightgrey", fg="black")

# Funkcja obsługi skrótu klawiszowego (lokalnego - F1)
def handle_shortcut(event):
    if event.keysym == 'F1':
        toggle_listening()

# Funkcja obsługi skrótu globalnego (Ctrl+Alt+R)
def start_global_hotkeys():
    def on_activate():
        print("Skrót globalny wykryty!")
        # Wywołujemy toggle w głównym wątku, żeby nie zawiesić GUI
        if root:
            root.after(0, toggle_listening)

    # Definicja skrótu
    hotkey = keyboard.GlobalHotKeys({
        '<ctrl>+<alt>+b': on_activate
    })
    hotkey.start()

# Tworzenie GUI
def create_gui():
    global toggle_button, emacs_button, root

    root = tk.Tk()
    root.title("Vosk Rozpoznawanie Mowy")
    root.geometry("300x200")

    toggle_button = tk.Button(root, text="Start", command=toggle_listening, width=15, bg="lightgrey", fg="black")
    toggle_button.pack(pady=10)

    emacs_button = tk.Button(root, text="Tryb: Standard", command=toggle_emacs_mode, width=15, bg="lightgrey", fg="black")
    emacs_button.pack(pady=10)

    exit_button = tk.Button(root, text="Wyjście", command=root.destroy, width=15)
    exit_button.pack(pady=10)

    # Dodanie skrótu klawiszowego lokalnego
    root.bind("<F1>", handle_shortcut)

    # Uruchomienie nasłuchiwania globalnych skrótów
    start_global_hotkeys()

    root.mainloop()

# Uruchomienie GUI
if __name__ == "__main__":
    create_gui()
